+2014-05-05 Richard Biener <rguenther@suse.de>
+
+ * passes.c (execute_function_todo): Move TODO_verify_flow under
+ the TODO_verify_ul umbrella.
+
+2014-05-05 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/61010
+ * fold-const.c (fold_binary_loc): Consistently avoid
+ canonicalizing X & CST away from a CST that is the mask
+ of a mode.
+
+2014-05-05 Jan-Benedict Glaw <jbglaw@lug-owl.de>
+
+ * config/picochip/picochip-protos.h (picochip_regno_nregs): Change
+ int argument to enum machine_mode.
+ (picochip_class_max_nregs): Ditto.
+ * config/picochip/picochip.c (picochip_regno_nregs): Ditto.
+ (picochip_class_max_nregs): Ditto.
+
+2014-05-05 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ * target.def: Add new target hook.
+ * doc/tm.texi: Regenerate.
+ * targhooks.h (default_keep_leaf_when_profiled): Add prototype.
+ * targhooks.c (default_keep_leaf_when_profiled): New function.
+
+ * config/s390/s390.c (s390_keep_leaf_when_profiled): New function.
+ (TARGET_KEEP_LEAF_WHEN_PROFILED): Define.
+
+2014-05-05 Bin Cheng <bin.cheng@arm.com>
+
+ PR tree-optimization/60363
+ * gcc/tree-ssa-threadupdate.c (get_value_locus_in_path): New.
+ (copy_phi_args): New parameters. Call get_value_locus_in_path.
+ (update_destination_phis): New parameter.
+ (create_edge_and_update_destination_phis): Ditto.
+ (ssa_fix_duplicate_block_edges): Pass new arguments.
+ (thread_single_edge): Ditto.
+
+2014-05-04 Peter Bergner <bergner@vnet.ibm.com>
+
+ * config/rs6000/rs6000.h (RS6000_BTM_HARD_FLOAT): New define.
+ (RS6000_BTM_COMMON): Add RS6000_BTM_HARD_FLOAT.
+ (TARGET_EXTRA_BUILTINS): Add TARGET_HARD_FLOAT.
+ * config/rs6000/rs6000-builtin.def (BU_MISC_1):
+ Use RS6000_BTM_HARD_FLOAT.
+ (BU_MISC_2): Likewise.
+ * config/rs6000/rs6000.c (rs6000_builtin_mask_calculate): Handle
+ RS6000_BTM_HARD_FLOAT.
+ (rs6000_option_override_internal): Enforce -mhard-float if -mhard-dfp
+ is explicitly used.
+ (rs6000_invalid_builtin): Add hard floating builtin support.
+ (rs6000_expand_builtin): Relax the gcc_assert to allow the new
+ hard float builtins.
+ (rs6000_builtin_mask_names): Add RS6000_BTM_HARD_FLOAT.
+
+2014-05-03 Oleg Endo <olegendo@gcc.gnu.org>
+
+ * config/sh/sh_optimize_sett_clrt.cc (sh_optimize_sett_clrt::execute):
+ Add missing function* argument.
+
+2014-05-03 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * lra-constraints.c (valid_address_p): Move earlier in file.
+ Add a constraint argument to the address_info version.
+ (satisfies_memory_constraint_p): New function.
+ (satisfies_address_constraint_p): Likewise.
+ (process_alt_operands, curr_insn_transform): Use them.
+ (process_address): Pass the constraint to valid_address_p when
+ checking address operands.
+
+2014-05-03 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * config/mips/mips.c (mips_isa_rev): New variable.
+ (mips_set_architecture): Set it.
+ * config/mips/mips.h (TARGET_CPU_CPP_BUILTINS): Set __mips_isa_rev
+ from mips_isa_rev.
+ (ISA_HAS_MUL3, ISA_HAS_FP_CONDMOVE, ISA_HAS_8CC, ISA_HAS_FP4)
+ (ISA_HAS_PAIRED_SINGLE, ISA_HAS_MADD_MSUB, ISA_HAS_FP_RECIP_RSQRT)
+ (ISA_HAS_CLZ_CLO, ISA_HAS_ROR, ISA_HAS_WSBH, ISA_HAS_PREFETCH)
+ (ISA_HAS_SEB_SEH, ISA_HAS_EXT_INS, ISA_HAS_MXHC1)
+ (ISA_HAS_HILO_INTERLOCKS, ISA_HAS_SYNCI, MIN_FPRS_PER_FMT): Reexpress
+ conditions in terms of mips_isa_rev.
+ (mips_isa_rev): Declare.
+
+2014-05-03 Oleg Endo <olegendo@gcc.gnu.org>
+
+ * config/sh/sh-mem.cc: Use tabs instead of spaces.
+ (prob_unlikely, prob_likely): Make variables const.
+
+2014-05-03 Denis Chertykov <chertykov@gmail.com>
+
+ * config/avr/avr.c (avr_adjust_insn_length): Handle JUMP_TABLE_DATA.
+
+2014-05-03 Oleg Endo <olegendo@gcc.gnu.org>
+
+ * config/sh/sh.h (SH_ASM_SPEC): Handle m1, m2*, m3* and m4* cases.
+
+2014-05-03 Oleg Endo <olegendo@gcc.gnu.org>
+
+ * config/sh/sh.h (ROUND_ADVANCE): Delete macro.
+ (ROUND_REG, PASS_IN_REG_P): Move and rename macros to ...
+ * config/sh/sh.c (sh_round_reg, sh_pass_in_reg_p): ... these new
+ functions.
+ (sh_arg_partial_bytes, sh_function_arg, sh_function_arg_advance,
+ sh_setup_incoming_varargs): Replace usage of PASS_IN_REG_P with
+ sh_pass_in_reg_p.
+ Replace usage of ROUND_REG with sh_round_reg.
+ Use CEIL instead of ROUND_ADVANCE.
+
+2014-05-03 Oleg Endo <olegendo@gcc.gnu.org>
+
+ PR target/61026
+ * config/sh/sh.c: Include stdlib headers before everything else.
+
+2014-05-02 Jakub Jelinek <jakub@redhat.com>
+
+ * gimplify.c (gimplify_adjust_omp_clauses_1): Handle
+ GOVD_FIRSTPRIVATE | GOVD_LASTPRIVATE.
+ (gimplify_adjust_omp_clauses): Simd region is never
+ directly nested in combined parallel. Instead, for linear
+ with copyin/copyout, if in combined for simd loop, make decl
+ firstprivate/lastprivate on OMP_FOR.
+ * omp-low.c (expand_omp_for_generic, expand_omp_for_static_nochunk,
+ expand_omp_for_static_chunk): When setting endvar, also set
+ fd->loop.v to the same value.
+
+2014-05-02 Richard Sandiford <rsandifo@linux.vnet.ibm.com>
+
+ * hwint.h (zext_hwi): Fix signed overflow for prec == 63.
+
+2014-05-02 Alan Lawrence <alan.lawrence@arm.com>
+
+ * config/aarch64/aarch64.c (aarch64_expand_vec_perm_1): Tidy bit-flip
+ expression.
+
+2014-05-02 Marek Polacek <polacek@redhat.com>
+
+ * doc/invoke.texi: Describe -fsanitize=float-divide-by-zero.
+
+2014-02-26 Kito Cheng <kito@0xlab.org>
+
+ * defaults.h (HONOR_REG_ALLOC_ORDER): Change HONOR_REG_ALLOC_ORDER
+ to a C expression marco.
+ * ira-color.c (HONOR_REG_ALLOC_ORDER) : Ditto.
+ * config/arm/arm.h (HONOR_REG_ALLOC_ORDER): Ditto.
+ * config/nds32/nds32.h (HONOR_REG_ALLOC_ORDER): Ditto.
+ * doc/tm.texi (HONOR_REG_ALLOC_ORDER): Update document for
+ HONOR_REG_ALLOC_ORDER.
+ * doc/tm.texi.in (HONOR_REG_ALLOC_ORDER): Ditto.
+
+2014-05-01 Jan-Benedict Glaw <jbglaw@lug-owl.de>
+
+ * config/arc/arc.c (TARGET_LRA_P): Undef before redefine.
+
+2014-05-01 Jan-Benedict Glaw <jbglaw@lug-owl.de>
+
+ * config/arc/arc.c (arc_select_cc_mode): Fix typo.
+
+2014-05-01 Yuri Rumyantsev <ysrumyan@gmail.com>
+
+ * tree-if-conv.c (is_cond_scalar_reduction): New function.
+ (convert_scalar_cond_reduction): Likewise.
+ (predicate_scalar_phi): Add recognition and transformation
+ of simple conditioanl reduction to be vectorizable.
+
+2014-05-01 Marek Polacek <polacek@redhat.com>
+
+ PR c/43245
+ * doc/invoke.texi: Document -Wdiscarded-qualifiers.
+
2014-04-30 Alan Lawrence <alan.lawrence@arm.com>
* config/aarch64/arm_neon.h (vuzp1_f32, vuzp1_p8, vuzp1_p16, vuzp1_s8,
+2014-05-02 Marek Polacek <polacek@redhat.com>
+
+ * c.opt (Wsizeof-pointer-memaccess): Describe option.
+
+2014-05-01 Marek Polacek <polacek@redhat.com>
+
+ PR c/43245
+ * c.opt (Wdiscarded-qualifiers): Add.
+
2014-04-30 Marek Polacek <polacek@redhat.com>
* c-ubsan.c (ubsan_instrument_division): Handle REAL_TYPEs. Perform
C C++ ObjC ObjC++ Var(warn_deprecated) Init(1) Warning
Warn if a deprecated compiler feature, class, method, or field is used
+Wdiscarded-qualifiers
+C ObjC Var(warn_discarded_qualifiers) Init(1) Warning
+Warn if type qualifiers on pointers are discarded
+
Wdiv-by-zero
C ObjC C++ ObjC++ Var(warn_div_by_zero) Init(1) Warning
Warn about compile-time integer division by zero
Wsizeof-pointer-memaccess
C ObjC C++ ObjC++ Var(warn_sizeof_pointer_memaccess) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
+Warn about suspicious length parameters to certain string functions if the argument uses sizeof
Wsuggest-attribute=format
C ObjC C++ ObjC++ Var(warn_suggest_attribute_format) Warning
+2014-05-02 Marek Polacek <polacek@redhat.com>
+
+ PR c/25801
+ * c-typeck.c (c_size_in_bytes): Update comment. Don't call error.
+ Return size_one_node when the type is not complete.
+ (pointer_diff): Remove comment.
+ (build_unary_op): Improve error messages.
+
+2014-05-02 Marek Polacek <polacek@redhat.com>
+
+ * c-typeck.c (c_finish_return): Separate warning_at calls.
+
+2014-05-02 Marek Polacek <polacek@redhat.com>
+
+ * c-tree.h (error_init): Remove declaration.
+ (pedwarn_init): Likewise.
+ * c-typeck.c (error_init): Make static and move above.
+ (pedwarn_init): Likewise.
+ (warning_init): Move above.
+ (maybe_warn_string_init): Likewise.
+
+2014-05-01 Jeff Law <law@redhat.com>
+
+ Revert:
+
+ 2014-04-24 Prathamesh Kulkarni <bilbotheelffriend@gmail.com>
+ * c-parser.c (c_parser_sizeof_expression): Reorganize slightly to
+ avoid goto.
+
+2014-05-02 Marek Polacek <polacek@redhat.com>
+
+ PR c/60784
+ * c-typeck.c (push_init_level): Set constructor_designated to
+ p->designated for structures.
+
+2014-05-01 Marek Polacek <polacek@redhat.com>
+
+ PR c/60915
+ * c-parser.c (c_parser_declaration_or_fndef): Give better error if
+ function-definition has an attribute after the declarator.
+
+2014-05-01 Marek Polacek <polacek@redhat.com>
+
+ PR c/60257
+ * c-typeck.c (warning_init): Add location_t parameter. Call
+ warning_at instead of warning.
+ (push_init_level): Pass input_location to warning_init.
+ (add_pending_init): Add location_t parameter. Pass loc to
+ warning_init.
+ (set_nonincremental_init): Pass input_location to add_pending_init.
+ (set_nonincremental_init_from_string): Likewise.
+ (output_init_element): Pass loc to warning_init and to
+ add_pending_init.
+
+2014-05-01 Marek Polacek <polacek@redhat.com>
+
+ PR c/43395
+ * c-typeck.c (c_finish_return): Distinguish between label and variable
+ when warning about returning local address.
+
+2014-05-01 Marek Polacek <polacek@redhat.com>
+
+ PR c/29467
+ * c-decl.c (declspecs_add_type): Pedwarn if boolean types are used
+ in C89 mode.
+
+2014-05-01 Marek Polacek <polacek@redhat.com>
+
+ PR c/43245
+ * c-typeck.c (convert_for_assignment): Pass OPT_Wdiscarded_qualifiers
+ instead of 0 to WARN_FOR_QUALIFIERS.
+
+2014-05-01 Marek Polacek <polacek@redhat.com>
+
+ PR c/56989
+ * c-typeck.c (default_conversion): Use better location for
+ error call.
+
2014-04-30 Marek Polacek <polacek@redhat.com>
* c-typeck.c (build_binary_op): Call ubsan_instrument_division
(process_init_element): Add location_t parameter. Pass loc to
output_init_element.
-2014-04-24 Prathamesh Kulkarni <bilbotheelffriend@gmail.com>
-
- * c-parser.c (c_parser_sizeof_expression): Reorganize slightly to
- avoid goto.
-
2014-04-24 Jakub Jelinek <jakub@redhat.com>
* c-parser.c (c_parser_omp_atomic): Allow seq_cst before
}
return specs;
case RID_BOOL:
+ if (!flag_isoc99 && !in_system_header_at (loc))
+ pedwarn (loc, OPT_Wpedantic,
+ "ISO C90 does not support boolean types");
if (specs->long_p)
error_at (loc,
("both %<long%> and %<_Bool%> in "
if (c_parser_next_token_is_keyword (parser, RID_ASM))
asm_name = c_parser_simple_asm_expr (parser);
if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
- postfix_attrs = c_parser_attributes (parser);
+ {
+ postfix_attrs = c_parser_attributes (parser);
+ if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
+ {
+ /* This means there is an attribute specifier after
+ the declarator in a function definition. Provide
+ some more information for the user. */
+ error_at (here, "attributes should be specified before the "
+ "declarator in a function definition");
+ c_parser_skip_to_end_of_block_or_statement (parser);
+ return;
+ }
+ }
if (c_parser_next_token_is (parser, CPP_EQ))
{
tree d;
return ret;
}
if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
- expr = c_parser_postfix_expression_after_paren_type (parser,
- type_name,
- expr_loc);
- else
{
- /* sizeof ( type-name ). */
- c_inhibit_evaluation_warnings--;
- in_sizeof--;
- return c_expr_sizeof_type (expr_loc, type_name);
+ expr = c_parser_postfix_expression_after_paren_type (parser,
+ type_name,
+ expr_loc);
+ goto sizeof_expr;
}
+ /* sizeof ( type-name ). */
+ c_inhibit_evaluation_warnings--;
+ in_sizeof--;
+ return c_expr_sizeof_type (expr_loc, type_name);
}
else
{
expr_loc = c_parser_peek_token (parser)->location;
expr = c_parser_unary_expression (parser);
+ sizeof_expr:
+ c_inhibit_evaluation_warnings--;
+ in_sizeof--;
+ mark_exp_read (expr.value);
+ if (TREE_CODE (expr.value) == COMPONENT_REF
+ && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
+ error_at (expr_loc, "%<sizeof%> applied to a bit-field");
+ return c_expr_sizeof_expr (expr_loc, expr);
}
- c_inhibit_evaluation_warnings--;
- in_sizeof--;
- mark_exp_read (expr.value);
- if (TREE_CODE (expr.value) == COMPONENT_REF
- && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
- error_at (expr_loc, "%<sizeof%> applied to a bit-field");
- return c_expr_sizeof_expr (expr_loc, expr);
}
/* Parse an alignof expression. */
extern tree c_cast_expr (location_t, struct c_type_name *, tree);
extern tree build_c_cast (location_t, tree, tree);
extern void store_init_value (location_t, tree, tree, tree);
-extern void error_init (const char *);
-extern void pedwarn_init (location_t, int opt, const char *);
extern void maybe_warn_string_init (tree, struct c_expr);
extern void start_init (tree, tree, int);
extern void finish_init (void);
static void push_member_name (tree);
static int spelling_length (void);
static char *print_spelling (char *);
-static void warning_init (int, const char *);
+static void warning_init (location_t, int, const char *);
static tree digest_init (location_t, tree, tree, tree, bool, bool, int);
static void output_init_element (location_t, tree, tree, bool, tree, tree, int,
bool, struct obstack *);
static void output_pending_init_elements (int, struct obstack *);
static int set_designator (int, struct obstack *);
static void push_range_stack (tree, struct obstack *);
-static void add_pending_init (tree, tree, tree, bool, struct obstack *);
+static void add_pending_init (location_t, tree, tree, tree, bool,
+ struct obstack *);
static void set_nonincremental_init (struct obstack *);
static void set_nonincremental_init_from_string (tree, struct obstack *);
static tree find_init_member (tree, struct obstack *);
}
}
\f
-/* Compute the size to increment a pointer by. */
+/* Compute the size to increment a pointer by. When a function type or void
+ type or incomplete type is passed, size_one_node is returned.
+ This function does not emit any diagnostics; the caller is responsible
+ for that. */
static tree
c_size_in_bytes (const_tree type)
{
enum tree_code code = TREE_CODE (type);
- if (code == FUNCTION_TYPE || code == VOID_TYPE || code == ERROR_MARK)
+ if (code == FUNCTION_TYPE || code == VOID_TYPE || code == ERROR_MARK
+ || !COMPLETE_TYPE_P (type))
return size_one_node;
- if (!COMPLETE_OR_VOID_TYPE_P (type))
- {
- error ("arithmetic on pointer to an incomplete type");
- return size_one_node;
- }
-
/* Convert in case a char is more than one unit. */
return size_binop_loc (input_location, CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
size_int (TYPE_PRECISION (char_type_node)
if (code == VOID_TYPE)
{
- error ("void value not ignored as it ought to be");
+ error_at (EXPR_LOC_OR_LOC (exp, input_location),
+ "void value not ignored as it ought to be");
return error_mark_node;
}
if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (orig_op1))))
error_at (loc, "arithmetic on pointer to an incomplete type");
- /* This generates an error if op0 is pointer to incomplete type. */
op1 = c_size_in_bytes (target_type);
if (pointer_to_zero_sized_aggr_p (TREE_TYPE (orig_op1)))
if (typecode == POINTER_TYPE)
{
- /* If pointer target is an undefined struct,
+ /* If pointer target is an incomplete type,
we just cannot know how to do the arithmetic. */
if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (argtype)))
{
if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
error_at (location,
- "increment of pointer to unknown structure");
+ "increment of pointer to an incomplete type %qT",
+ TREE_TYPE (argtype));
else
error_at (location,
- "decrement of pointer to unknown structure");
+ "decrement of pointer to an incomplete type %qT",
+ TREE_TYPE (argtype));
}
else if (TREE_CODE (TREE_TYPE (argtype)) == FUNCTION_TYPE
|| TREE_CODE (TREE_TYPE (argtype)) == VOID_TYPE)
return ret;
}
+/* Issue an error message for a bad initializer component.
+ GMSGID identifies the message.
+ The component name is taken from the spelling stack. */
+
+static void
+error_init (const char *gmsgid)
+{
+ char *ofwhat;
+
+ /* The gmsgid may be a format string with %< and %>. */
+ error (gmsgid);
+ ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
+ if (*ofwhat)
+ error ("(near initialization for %qs)", ofwhat);
+}
+
+/* Issue a pedantic warning for a bad initializer component. OPT is
+ the option OPT_* (from options.h) controlling this warning or 0 if
+ it is unconditionally given. GMSGID identifies the message. The
+ component name is taken from the spelling stack. */
+
+static void
+pedwarn_init (location_t location, int opt, const char *gmsgid)
+{
+ char *ofwhat;
+
+ /* The gmsgid may be a format string with %< and %>. */
+ pedwarn (location, opt, gmsgid);
+ ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
+ if (*ofwhat)
+ pedwarn (location, opt, "(near initialization for %qs)", ofwhat);
+}
+
+/* Issue a warning for a bad initializer component.
+
+ OPT is the OPT_W* value corresponding to the warning option that
+ controls this warning. GMSGID identifies the message. The
+ component name is taken from the spelling stack. */
+
+static void
+warning_init (location_t loc, int opt, const char *gmsgid)
+{
+ char *ofwhat;
+
+ /* The gmsgid may be a format string with %< and %>. */
+ warning_at (loc, opt, gmsgid);
+ ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
+ if (*ofwhat)
+ warning_at (loc, opt, "(near initialization for %qs)", ofwhat);
+}
+\f
+/* If TYPE is an array type and EXPR is a parenthesized string
+ constant, warn if pedantic that EXPR is being used to initialize an
+ object of type TYPE. */
+
+void
+maybe_warn_string_init (tree type, struct c_expr expr)
+{
+ if (pedantic
+ && TREE_CODE (type) == ARRAY_TYPE
+ && TREE_CODE (expr.value) == STRING_CST
+ && expr.original_code != STRING_CST)
+ pedwarn_init (input_location, OPT_Wpedantic,
+ "array initialized from parenthesized string constant");
+}
+
/* Convert value RHS to type TYPE as preparation for an assignment to
an lvalue of type TYPE. If ORIGTYPE is not NULL_TREE, it is the
original type of RHS; this differs from TREE_TYPE (RHS) for enum
vice-versa. */
if (TYPE_QUALS_NO_ADDR_SPACE (ttl)
& ~TYPE_QUALS_NO_ADDR_SPACE (ttr))
- WARN_FOR_QUALIFIERS (location, 0,
+ WARN_FOR_QUALIFIERS (location, OPT_Wdiscarded_qualifiers,
G_("passing argument %d of %qE "
"makes %q#v qualified function "
"pointer from unqualified"),
}
else if (TYPE_QUALS_NO_ADDR_SPACE (ttr)
& ~TYPE_QUALS_NO_ADDR_SPACE (ttl))
- WARN_FOR_QUALIFIERS (location, 0,
+ WARN_FOR_QUALIFIERS (location, OPT_Wdiscarded_qualifiers,
G_("passing argument %d of %qE discards "
"%qv qualifier from pointer target type"),
G_("assignment discards %qv qualifier "
if (TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttr)
& ~TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttl))
{
- WARN_FOR_QUALIFIERS (location, 0,
+ WARN_FOR_QUALIFIERS (location, OPT_Wdiscarded_qualifiers,
G_("passing argument %d of %qE discards "
"%qv qualifier from pointer target type"),
G_("assignment discards %qv qualifier "
where an ordinary one is wanted, but not vice-versa. */
if (TYPE_QUALS_NO_ADDR_SPACE (ttl)
& ~TYPE_QUALS_NO_ADDR_SPACE (ttr))
- WARN_FOR_QUALIFIERS (location, 0,
+ WARN_FOR_QUALIFIERS (location, OPT_Wdiscarded_qualifiers,
G_("passing argument %d of %qE makes "
"%q#v qualified function pointer "
"from unqualified"),
return buffer;
}
-/* Issue an error message for a bad initializer component.
- GMSGID identifies the message.
- The component name is taken from the spelling stack. */
-
-void
-error_init (const char *gmsgid)
-{
- char *ofwhat;
-
- /* The gmsgid may be a format string with %< and %>. */
- error (gmsgid);
- ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
- if (*ofwhat)
- error ("(near initialization for %qs)", ofwhat);
-}
-
-/* Issue a pedantic warning for a bad initializer component. OPT is
- the option OPT_* (from options.h) controlling this warning or 0 if
- it is unconditionally given. GMSGID identifies the message. The
- component name is taken from the spelling stack. */
-
-void
-pedwarn_init (location_t location, int opt, const char *gmsgid)
-{
- char *ofwhat;
-
- /* The gmsgid may be a format string with %< and %>. */
- pedwarn (location, opt, gmsgid);
- ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
- if (*ofwhat)
- pedwarn (location, opt, "(near initialization for %qs)", ofwhat);
-}
-
-/* Issue a warning for a bad initializer component.
-
- OPT is the OPT_W* value corresponding to the warning option that
- controls this warning. GMSGID identifies the message. The
- component name is taken from the spelling stack. */
-
-static void
-warning_init (int opt, const char *gmsgid)
-{
- char *ofwhat;
-
- /* The gmsgid may be a format string with %< and %>. */
- warning (opt, gmsgid);
- ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
- if (*ofwhat)
- warning (opt, "(near initialization for %qs)", ofwhat);
-}
-\f
-/* If TYPE is an array type and EXPR is a parenthesized string
- constant, warn if pedantic that EXPR is being used to initialize an
- object of type TYPE. */
-
-void
-maybe_warn_string_init (tree type, struct c_expr expr)
-{
- if (pedantic
- && TREE_CODE (type) == ARRAY_TYPE
- && TREE_CODE (expr.value) == STRING_CST
- && expr.original_code != STRING_CST)
- pedwarn_init (input_location, OPT_Wpedantic,
- "array initialized from parenthesized string constant");
-}
-
/* Digest the parser output INIT as an initializer for type TYPE.
Return a C expression of type TYPE to represent the initial value.
push_member_name (constructor_fields);
constructor_depth++;
}
+ /* If upper initializer is designated, then mark this as
+ designated too to prevent bogus warnings. */
+ constructor_designated = p->designated;
}
else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
{
if (implicit == 1 && warn_missing_braces && !missing_braces_mentioned)
{
missing_braces_mentioned = 1;
- warning_init (OPT_Wmissing_braces, "missing braces around initializer");
+ warning_init (input_location, OPT_Wmissing_braces,
+ "missing braces around initializer");
}
if (TREE_CODE (constructor_type) == RECORD_TYPE
else
{
if (constructor_type != error_mark_node)
- warning_init (0, "braces around scalar initializer");
+ warning_init (input_location, 0, "braces around scalar initializer");
constructor_fields = constructor_type;
constructor_unfilled_fields = constructor_type;
}
existing initializer. */
static void
-add_pending_init (tree purpose, tree value, tree origtype, bool implicit,
- struct obstack * braced_init_obstack)
+add_pending_init (location_t loc, tree purpose, tree value, tree origtype,
+ bool implicit, struct obstack *braced_init_obstack)
{
struct init_node *p, **q, *r;
if (!implicit)
{
if (TREE_SIDE_EFFECTS (p->value))
- warning_init (0, "initialized field with side-effects overwritten");
+ warning_init (loc, 0,
+ "initialized field with side-effects "
+ "overwritten");
else if (warn_override_init)
- warning_init (OPT_Woverride_init, "initialized field overwritten");
+ warning_init (loc, OPT_Woverride_init,
+ "initialized field overwritten");
}
p->value = value;
p->origtype = origtype;
if (!implicit)
{
if (TREE_SIDE_EFFECTS (p->value))
- warning_init (0, "initialized field with side-effects overwritten");
+ warning_init (loc, 0,
+ "initialized field with side-effects "
+ "overwritten");
else if (warn_override_init)
- warning_init (OPT_Woverride_init, "initialized field overwritten");
+ warning_init (loc, OPT_Woverride_init,
+ "initialized field overwritten");
}
p->value = value;
p->origtype = origtype;
return;
FOR_EACH_CONSTRUCTOR_ELT (constructor_elements, ix, index, value)
- {
- add_pending_init (index, value, NULL_TREE, true,
- braced_init_obstack);
- }
+ add_pending_init (input_location, index, value, NULL_TREE, true,
+ braced_init_obstack);
constructor_elements = NULL;
if (TREE_CODE (constructor_type) == RECORD_TYPE)
{
value = wide_int_to_tree (type,
wide_int::from_array (val, 2,
HOST_BITS_PER_WIDE_INT * 2));
- add_pending_init (purpose, value, NULL_TREE, true,
+ add_pending_init (input_location, purpose, value, NULL_TREE, true,
braced_init_obstack);
}
if (checktype != error_mark_node
&& (TYPE_MAIN_VARIANT (checktype)
!= TYPE_MAIN_VARIANT (DECL_BIT_FIELD_TYPE (field))))
- warning_init (OPT_Wc___compat,
+ warning_init (loc, OPT_Wc___compat,
"enum conversion in initialization is invalid in C++");
}
&& tree_int_cst_lt (field, constructor_unfilled_index))
set_nonincremental_init (braced_init_obstack);
- add_pending_init (field, value, origtype, implicit,
+ add_pending_init (loc, field, value, origtype, implicit,
braced_init_obstack);
return;
}
}
}
- add_pending_init (field, value, origtype, implicit,
+ add_pending_init (loc, field, value, origtype, implicit,
braced_init_obstack);
return;
}
if (!implicit)
{
if (TREE_SIDE_EFFECTS (constructor_elements->last ().value))
- warning_init (0,
+ warning_init (loc, 0,
"initialized field with side-effects overwritten");
else if (warn_override_init)
- warning_init (OPT_Woverride_init, "initialized field overwritten");
+ warning_init (loc, OPT_Woverride_init,
+ "initialized field overwritten");
}
/* We can have just one union field set. */
&& !DECL_EXTERNAL (inner)
&& !TREE_STATIC (inner)
&& DECL_CONTEXT (inner) == current_function_decl)
- warning_at (loc,
- OPT_Wreturn_local_addr, "function returns address "
- "of local variable");
+ {
+ if (TREE_CODE (inner) == LABEL_DECL)
+ warning_at (loc, OPT_Wreturn_local_addr,
+ "function returns address of label");
+ else
+ warning_at (loc, OPT_Wreturn_local_addr,
+ "function returns address of local variable");
+ }
break;
default:
unsigned i, nelt = d->nelt;
rtx x;
+ gcc_assert (nelt == (nelt & -nelt));
for (i = 0; i < nelt; ++i)
- d->perm[i] = (d->perm[i] + nelt) & (2 * nelt - 1);
+ d->perm[i] ^= nelt; /* Keep the same index, but in the other vector. */
x = d->op0;
d->op0 = d->op1;
#define TARGET_INSN_LENGTH_PARAMETERS arc_insn_length_parameters
+#undef TARGET_LRA_P
#define TARGET_LRA_P arc_lra_p
#define TARGET_REGISTER_PRIORITY arc_register_priority
/* Stores with scaled offsets have different displacement ranges. */
if (GET_MODE_CLASS (mode) == MODE_INT
&& y == const0_rtx
&& (op == EQ || op == NE
- || ((op == LT || op == GE) && GET_MODE_SIZE (GET_MODE (x)) <= 4))))
+ || ((op == LT || op == GE) && GET_MODE_SIZE (GET_MODE (x)) <= 4)))
return CC_ZNmode;
/* add.f for if (a+b) */
/* Tell IRA to use the order we define rather than messing it up with its
own cost calculations. */
-#define HONOR_REG_ALLOC_ORDER
+#define HONOR_REG_ALLOC_ORDER 1
/* Interrupt functions can only use registers that have already been
saved by the prologue, even if they would normally be
the length need not/must not be adjusted for these insns.
It is easier to state this in an insn attribute "adjust_len" than
to clutter up code here... */
-
- if (-1 == recog_memoized (insn))
+
+ if (JUMP_TABLE_DATA_P (insn) || recog_memoized (insn) == -1)
{
return len;
}
/* The ISA level associated with mips_arch. */
int mips_isa;
+/* The ISA revision level. This is 0 for MIPS I to V and N for
+ MIPS{32,64}rN. */
+int mips_isa_rev;
+
/* The architecture selected by -mipsN, or null if -mipsN wasn't used. */
static const struct mips_cpu_info *mips_isa_option_info;
mips_arch_info = info;
mips_arch = info->cpu;
mips_isa = info->isa;
+ if (mips_isa < 32)
+ mips_isa_rev = 0;
+ else
+ mips_isa_rev = (mips_isa & 31) + 1;
}
}
else if (ISA_MIPS32) \
{ \
builtin_define ("__mips=32"); \
- builtin_define ("__mips_isa_rev=1"); \
builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS32"); \
} \
else if (ISA_MIPS32R2) \
{ \
builtin_define ("__mips=32"); \
- builtin_define ("__mips_isa_rev=2"); \
builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS32"); \
} \
else if (ISA_MIPS64) \
{ \
builtin_define ("__mips=64"); \
- builtin_define ("__mips_isa_rev=1"); \
builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS64"); \
} \
else if (ISA_MIPS64R2) \
{ \
builtin_define ("__mips=64"); \
- builtin_define ("__mips_isa_rev=2"); \
builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS64"); \
} \
+ if (mips_isa_rev > 0) \
+ builtin_define_with_int_value ("__mips_isa_rev", \
+ mips_isa_rev); \
\
switch (mips_abi) \
{ \
|| TARGET_MIPS7000 \
|| TARGET_MIPS9000 \
|| TARGET_MAD \
- || ISA_MIPS32 \
- || ISA_MIPS32R2 \
- || ISA_MIPS64 \
- || ISA_MIPS64R2) \
+ || mips_isa_rev >= 1) \
&& !TARGET_MIPS16)
/* ISA has a three-operand multiplication instruction. */
/* ISA has the floating-point conditional move instructions introduced
in mips4. */
#define ISA_HAS_FP_CONDMOVE ((ISA_MIPS4 \
- || ISA_MIPS32 \
- || ISA_MIPS32R2 \
- || ISA_MIPS64 \
- || ISA_MIPS64R2) \
+ || mips_isa_rev >= 1) \
&& !TARGET_MIPS5500 \
&& !TARGET_MIPS16)
/* ISA has the mips4 FP condition code instructions: FP-compare to CC,
branch on CC, and move (both FP and non-FP) on CC. */
-#define ISA_HAS_8CC (ISA_MIPS4 \
- || ISA_MIPS32 \
- || ISA_MIPS32R2 \
- || ISA_MIPS64 \
- || ISA_MIPS64R2)
+#define ISA_HAS_8CC (ISA_MIPS4 || mips_isa_rev >= 1)
/* This is a catch all for other mips4 instructions: indexed load, the
FP madd and msub instructions, and the FP recip and recip sqrt
instructions. Note that this macro should only be used by other
ISA_HAS_* macros. */
#define ISA_HAS_FP4 ((ISA_MIPS4 \
- || ISA_MIPS32R2 \
|| ISA_MIPS64 \
- || ISA_MIPS64R2) \
+ || mips_isa_rev >= 2) \
&& !TARGET_MIPS16)
/* ISA has floating-point indexed load and store instructions
#define ISA_HAS_LXC1_SXC1 ISA_HAS_FP4
/* ISA has paired-single instructions. */
-#define ISA_HAS_PAIRED_SINGLE (ISA_MIPS32R2 || ISA_MIPS64 || ISA_MIPS64R2)
+#define ISA_HAS_PAIRED_SINGLE (ISA_MIPS64 || mips_isa_rev >= 2)
/* ISA has conditional trap instructions. */
#define ISA_HAS_COND_TRAP (!ISA_MIPS1 \
&& !TARGET_MIPS16)
/* ISA has integer multiply-accumulate instructions, madd and msub. */
-#define ISA_HAS_MADD_MSUB (ISA_MIPS32 \
- || ISA_MIPS32R2 \
- || ISA_MIPS64 \
- || ISA_MIPS64R2)
+#define ISA_HAS_MADD_MSUB (mips_isa_rev >= 1)
/* Integer multiply-accumulate instructions should be generated. */
#define GENERATE_MADD_MSUB (TARGET_IMADD && !TARGET_MIPS16)
(((ISA_HAS_FP4 \
&& ((MODE) == SFmode \
|| ((TARGET_FLOAT64 \
- || ISA_MIPS32R2 \
- || ISA_MIPS64R2) \
+ || mips_isa_rev >= 2) \
&& (MODE) == DFmode))) \
|| (TARGET_SB1 \
&& (MODE) == V2SFmode)) \
&& !TARGET_MIPS16)
/* ISA has count leading zeroes/ones instruction (not implemented). */
-#define ISA_HAS_CLZ_CLO ((ISA_MIPS32 \
- || ISA_MIPS32R2 \
- || ISA_MIPS64 \
- || ISA_MIPS64R2) \
- && !TARGET_MIPS16)
+#define ISA_HAS_CLZ_CLO (mips_isa_rev >= 1 && !TARGET_MIPS16)
/* ISA has three operand multiply instructions that put
the high part in an accumulator: mulhi or mulhiu. */
&& !TARGET_MIPS16)
/* ISA has the "ror" (rotate right) instructions. */
-#define ISA_HAS_ROR ((ISA_MIPS32R2 \
- || ISA_MIPS64R2 \
+#define ISA_HAS_ROR ((mips_isa_rev >= 2 \
|| TARGET_MIPS5400 \
|| TARGET_MIPS5500 \
|| TARGET_SR71K \
/* ISA has the WSBH (word swap bytes within halfwords) instruction.
64-bit targets also provide DSBH and DSHD. */
-#define ISA_HAS_WSBH ((ISA_MIPS32R2 || ISA_MIPS64R2) \
- && !TARGET_MIPS16)
+#define ISA_HAS_WSBH (mips_isa_rev >= 2 && !TARGET_MIPS16)
/* ISA has data prefetch instructions. This controls use of 'pref'. */
#define ISA_HAS_PREFETCH ((ISA_MIPS4 \
|| TARGET_LOONGSON_2EF \
|| TARGET_MIPS5900 \
- || ISA_MIPS32 \
- || ISA_MIPS32R2 \
- || ISA_MIPS64 \
- || ISA_MIPS64R2) \
+ || mips_isa_rev >= 1) \
&& !TARGET_MIPS16)
/* ISA has data indexed prefetch instructions. This controls use of
#define ISA_HAS_TRUNC_W (!ISA_MIPS1)
/* ISA includes the MIPS32r2 seb and seh instructions. */
-#define ISA_HAS_SEB_SEH ((ISA_MIPS32R2 \
- || ISA_MIPS64R2) \
- && !TARGET_MIPS16)
+#define ISA_HAS_SEB_SEH (mips_isa_rev >= 2 && !TARGET_MIPS16)
/* ISA includes the MIPS32/64 rev 2 ext and ins instructions. */
-#define ISA_HAS_EXT_INS ((ISA_MIPS32R2 \
- || ISA_MIPS64R2) \
- && !TARGET_MIPS16)
+#define ISA_HAS_EXT_INS (mips_isa_rev >= 2 && !TARGET_MIPS16)
/* ISA has instructions for accessing top part of 64-bit fp regs. */
-#define ISA_HAS_MXHC1 (TARGET_FLOAT64 \
- && (ISA_MIPS32R2 \
- || ISA_MIPS64R2))
+#define ISA_HAS_MXHC1 (TARGET_FLOAT64 && mips_isa_rev >= 2)
/* ISA has lwxs instruction (load w/scaled index address. */
#define ISA_HAS_LWXS ((TARGET_SMARTMIPS || TARGET_MICROMIPS) \
MIPS64 and later ISAs to have the interlocks, plus any specific
earlier-ISA CPUs for which CPU documentation declares that the
instructions are really interlocked. */
-#define ISA_HAS_HILO_INTERLOCKS (ISA_MIPS32 \
- || ISA_MIPS32R2 \
- || ISA_MIPS64 \
- || ISA_MIPS64R2 \
+#define ISA_HAS_HILO_INTERLOCKS (mips_isa_rev >= 1 \
|| TARGET_MIPS5500 \
|| TARGET_MIPS5900 \
|| TARGET_LOONGSON_2EF)
/* ISA includes synci, jr.hb and jalr.hb. */
-#define ISA_HAS_SYNCI ((ISA_MIPS32R2 \
- || ISA_MIPS64R2) \
- && !TARGET_MIPS16)
+#define ISA_HAS_SYNCI (mips_isa_rev >= 2 && !TARGET_MIPS16)
/* ISA includes sync. */
#define ISA_HAS_SYNC ((mips_isa >= 2 || TARGET_MIPS3900) && !TARGET_MIPS16)
/* The number of consecutive floating-point registers needed to store the
smallest format supported by the FPU. */
#define MIN_FPRS_PER_FMT \
- (ISA_MIPS32 || ISA_MIPS32R2 || ISA_MIPS64 || ISA_MIPS64R2 \
- ? 1 : MAX_FPRS_PER_FMT)
+ (mips_isa_rev >= 1 ? 1 : MAX_FPRS_PER_FMT)
/* The largest size of value that can be held in floating-point
registers and moved with a single instruction. */
extern enum processor mips_arch; /* which cpu to codegen for */
extern enum processor mips_tune; /* which cpu to schedule for */
extern int mips_isa; /* architectural level */
+extern int mips_isa_rev;
extern const struct mips_cpu_info *mips_arch_info;
extern const struct mips_cpu_info *mips_tune_info;
extern unsigned int mips_base_compression_flags;
/* Tell IRA to use the order we define rather than messing it up with its
own cost calculations. */
-#define HONOR_REG_ALLOC_ORDER
+#define HONOR_REG_ALLOC_ORDER 1
/* The number of consecutive hard regs needed starting at
reg "regno" for holding a value of mode "mode". */
extern rtx gen_min_reg(rtx opnd1,rtx opnd2);
-extern int picochip_regno_nregs (int regno, int mode);
-extern int picochip_class_max_nregs (int klass, int mode);
+extern int picochip_regno_nregs (int regno, enum machine_mode mode);
+extern int picochip_class_max_nregs (int klass, enum machine_mode mode);
extern void picochip_order_regs_for_local_alloc (void);
}
int
-picochip_regno_nregs (int regno ATTRIBUTE_UNUSED, int mode)
+picochip_regno_nregs (int regno ATTRIBUTE_UNUSED, enum machine_mode mode)
{
/* Special case - only one register needed. */
}
int
-picochip_class_max_nregs (int reg_class, int mode)
+picochip_class_max_nregs (int reg_class, enum machine_mode mode)
{
int size = ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
#define BU_MISC_1(ENUM, NAME, ATTR, ICODE) \
RS6000_BUILTIN_2 (MISC_BUILTIN_ ## ENUM, /* ENUM */ \
"__builtin_" NAME, /* NAME */ \
- RS6000_BTM_ALWAYS, /* MASK */ \
+ RS6000_BTM_HARD_FLOAT, /* MASK */ \
(RS6000_BTC_ ## ATTR /* ATTR */ \
| RS6000_BTC_UNARY), \
CODE_FOR_ ## ICODE) /* ICODE */
#define BU_MISC_2(ENUM, NAME, ATTR, ICODE) \
RS6000_BUILTIN_2 (MISC_BUILTIN_ ## ENUM, /* ENUM */ \
"__builtin_" NAME, /* NAME */ \
- RS6000_BTM_ALWAYS, /* MASK */ \
+ RS6000_BTM_HARD_FLOAT, /* MASK */ \
(RS6000_BTC_ ## ATTR /* ATTR */ \
| RS6000_BTC_BINARY), \
CODE_FOR_ ## ICODE) /* ICODE */
| ((TARGET_P8_VECTOR) ? RS6000_BTM_P8_VECTOR : 0)
| ((TARGET_CRYPTO) ? RS6000_BTM_CRYPTO : 0)
| ((TARGET_HTM) ? RS6000_BTM_HTM : 0)
- | ((TARGET_DFP) ? RS6000_BTM_DFP : 0));
+ | ((TARGET_DFP) ? RS6000_BTM_DFP : 0)
+ | ((TARGET_HARD_FLOAT) ? RS6000_BTM_HARD_FLOAT : 0));
}
/* Override command line options. Mostly we process the processor type and
rs6000_isa_flags &= ~OPTION_MASK_VSX_TIMODE;
}
+ if (TARGET_DFP && !TARGET_HARD_FLOAT)
+ {
+ if (rs6000_isa_flags_explicit & OPTION_MASK_DFP)
+ error ("-mhard-dfp requires -mhard-float");
+ rs6000_isa_flags &= ~OPTION_MASK_DFP;
+ }
+
/* The quad memory instructions only works in 64-bit mode. In 32-bit mode,
silently turn off quad memory mode. */
if ((TARGET_QUAD_MEMORY || TARGET_QUAD_MEMORY_ATOMIC) && !TARGET_POWERPC64)
error ("Builtin function %s requires the -mhard-dfp option", name);
else if ((fnmask & RS6000_BTM_P8_VECTOR) != 0)
error ("Builtin function %s requires the -mpower8-vector option", name);
+ else if ((fnmask & RS6000_BTM_HARD_FLOAT) != 0)
+ error ("Builtin function %s requires the -mhard-float option", name);
else
error ("Builtin function %s is not supported with the current options",
name);
return ret;
}
- gcc_assert (TARGET_ALTIVEC || TARGET_VSX || TARGET_SPE || TARGET_PAIRED_FLOAT);
+ unsigned attr = rs6000_builtin_info[uns_fcode].attr & RS6000_BTC_TYPE_MASK;
+ gcc_assert (attr == RS6000_BTC_UNARY
+ || attr == RS6000_BTC_BINARY
+ || attr == RS6000_BTC_TERNARY);
/* Handle simple unary operations. */
d = bdesc_1arg;
{ "crypto", RS6000_BTM_CRYPTO, false, false },
{ "htm", RS6000_BTM_HTM, false, false },
{ "hard-dfp", RS6000_BTM_DFP, false, false },
+ { "hard-float", RS6000_BTM_HARD_FLOAT, false, false },
};
/* Option variables that we want to support inside attribute((target)) and
|| TARGET_CMPB /* ISA 2.05 */ \
|| TARGET_POPCNTD /* ISA 2.06 */ \
|| TARGET_ALTIVEC \
- || TARGET_VSX)))
+ || TARGET_VSX \
+ || TARGET_HARD_FLOAT)))
/* E500 cores only support plain "sync", not lwsync. */
#define TARGET_NO_LWSYNC (rs6000_cpu == PROCESSOR_PPC8540 \
#define RS6000_BTM_POPCNTD MASK_POPCNTD /* Target supports ISA 2.06. */
#define RS6000_BTM_CELL MASK_FPRND /* Target is cell powerpc. */
#define RS6000_BTM_DFP MASK_DFP /* Decimal floating point. */
+#define RS6000_BTM_HARD_FLOAT MASK_SOFT_FLOAT /* Hardware floating point. */
#define RS6000_BTM_COMMON (RS6000_BTM_ALTIVEC \
| RS6000_BTM_VSX \
| RS6000_BTM_HTM \
| RS6000_BTM_POPCNTD \
| RS6000_BTM_CELL \
- | RS6000_BTM_DFP)
+ | RS6000_BTM_DFP \
+ | RS6000_BTM_HARD_FLOAT)
/* Define builtin enum index. */
return const0_rtx;
}
+/* We call mcount before the function prologue. So a profiled leaf
+ function should stay a leaf function. */
+
+static bool
+s390_keep_leaf_when_profiled ()
+{
+ return true;
+}
/* Output assembly code for the trampoline template to
stdio stream FILE.
#undef TARGET_LIBCALL_VALUE
#define TARGET_LIBCALL_VALUE s390_libcall_value
+#undef TARGET_KEEP_LEAF_WHEN_PROFILED
+#define TARGET_KEEP_LEAF_WHEN_PROFILED s390_keep_leaf_when_profiled
+
#undef TARGET_FIXED_CONDITION_CODE_REGS
#define TARGET_FIXED_CONDITION_CODE_REGS s390_fixed_condition_code_regs
return false;
}
-static int prob_unlikely = REG_BR_PROB_BASE / 10;
-static int prob_likely = REG_BR_PROB_BASE / 4;
+static const int prob_unlikely = REG_BR_PROB_BASE / 10;
+static const int prob_likely = REG_BR_PROB_BASE / 4;
/* Emit code to perform a strcmp.
emit_move_insn (tmp3, addr2);
emit_move_insn (s2_addr, plus_constant (Pmode, s2_addr, 4));
- /*start long loop. */
+ /* start long loop. */
emit_label (L_loop_long);
emit_move_insn (tmp2, tmp3);
rtx len = force_reg (SImode, operands[3]);
int constp = CONST_INT_P (operands[3]);
- /* Loop on a register count. */
+ /* Loop on a register count. */
if (constp)
{
rtx tmp0 = gen_reg_rtx (SImode);
int witers = bytes / 4;
if (witers > 1)
- {
- addr1 = adjust_automodify_address (addr1, SImode, s1_addr, 0);
- addr2 = adjust_automodify_address (addr2, SImode, s2_addr, 0);
-
- emit_move_insn (tmp0, const0_rtx);
-
- if (align < 4)
- {
- emit_insn (gen_iorsi3 (tmp1, s1_addr, s2_addr));
- emit_insn (gen_tstsi_t (GEN_INT (3), tmp1));
- jump = emit_jump_insn (gen_branch_false (L_loop_byte));
- add_int_reg_note (jump, REG_BR_PROB, prob_likely);
- }
-
- /* word count. Do we have iterations ? */
- emit_insn (gen_lshrsi3 (lenw, len, GEN_INT (2)));
-
- /*start long loop. */
- emit_label (L_loop_long);
-
- /* tmp2 is aligned, OK to load. */
- emit_move_insn (tmp2, addr2);
- emit_move_insn (s2_addr, plus_constant (Pmode, s2_addr,
- GET_MODE_SIZE (SImode)));
-
- /* tmp1 is aligned, OK to load. */
- emit_move_insn (tmp1, addr1);
- emit_move_insn (s1_addr, plus_constant (Pmode, s1_addr,
- GET_MODE_SIZE (SImode)));
-
- /* Is there a 0 byte ? */
- emit_insn (gen_andsi3 (tmp3, tmp2, tmp1));
-
- emit_insn (gen_cmpstr_t (tmp0, tmp3));
- jump = emit_jump_insn (gen_branch_true (L_end_loop_long));
- add_int_reg_note (jump, REG_BR_PROB, prob_unlikely);
-
- emit_insn (gen_cmpeqsi_t (tmp1, tmp2));
- jump = emit_jump_insn (gen_branch_false (L_end_loop_long));
- add_int_reg_note (jump, REG_BR_PROB, prob_unlikely);
-
- if (TARGET_SH2)
- emit_insn (gen_dect (lenw, lenw));
- else
- {
- emit_insn (gen_addsi3 (lenw, lenw, GEN_INT (-1)));
- emit_insn (gen_tstsi_t (lenw, lenw));
- }
-
- jump = emit_jump_insn (gen_branch_false (L_loop_long));
- add_int_reg_note (jump, REG_BR_PROB, prob_likely);
-
- int sbytes = bytes % 4;
-
- /* end loop. Reached max iterations. */
- if (! sbytes)
- {
- jump = emit_jump_insn (gen_jump_compact (L_return));
- emit_barrier_after (jump);
- }
- else
- {
- /* Remaining bytes to check. */
-
- addr1 = adjust_automodify_address (addr1, QImode, s1_addr, 0);
- addr2 = adjust_automodify_address (addr2, QImode, s2_addr, 0);
-
- while (sbytes--)
- {
- emit_insn (gen_extendqisi2 (tmp1, addr1));
- emit_insn (gen_extendqisi2 (tmp2, addr2));
-
- emit_insn (gen_cmpeqsi_t (tmp2, const0_rtx));
- jump = emit_jump_insn (gen_branch_true (L_end_loop_byte));
- add_int_reg_note (jump, REG_BR_PROB, prob_unlikely);
-
- emit_insn (gen_cmpeqsi_t (tmp1, tmp2));
- if (flag_delayed_branch)
- emit_insn (gen_zero_extendqisi2 (tmp2,
- gen_lowpart (QImode,
- tmp2)));
- jump = emit_jump_insn (gen_branch_false (L_end_loop_byte));
- add_int_reg_note (jump, REG_BR_PROB, prob_unlikely);
-
- addr1 = adjust_address (addr1, QImode,
- GET_MODE_SIZE (QImode));
- addr2 = adjust_address (addr2, QImode,
- GET_MODE_SIZE (QImode));
- }
-
- jump = emit_jump_insn (gen_jump_compact( L_end_loop_byte));
- emit_barrier_after (jump);
- }
-
- emit_label (L_end_loop_long);
-
- /* Found last word. Restart it byte per byte. */
-
- emit_move_insn (s1_addr, plus_constant (Pmode, s1_addr,
- -GET_MODE_SIZE (SImode)));
- emit_move_insn (s2_addr, plus_constant (Pmode, s2_addr,
- -GET_MODE_SIZE (SImode)));
-
- /* fall thru. */
- }
+ {
+ addr1 = adjust_automodify_address (addr1, SImode, s1_addr, 0);
+ addr2 = adjust_automodify_address (addr2, SImode, s2_addr, 0);
+
+ emit_move_insn (tmp0, const0_rtx);
+
+ if (align < 4)
+ {
+ emit_insn (gen_iorsi3 (tmp1, s1_addr, s2_addr));
+ emit_insn (gen_tstsi_t (GEN_INT (3), tmp1));
+ jump = emit_jump_insn (gen_branch_false (L_loop_byte));
+ add_int_reg_note (jump, REG_BR_PROB, prob_likely);
+ }
+
+ /* word count. Do we have iterations ? */
+ emit_insn (gen_lshrsi3 (lenw, len, GEN_INT (2)));
+
+ /* start long loop. */
+ emit_label (L_loop_long);
+
+ /* tmp2 is aligned, OK to load. */
+ emit_move_insn (tmp2, addr2);
+ emit_move_insn (s2_addr, plus_constant (Pmode, s2_addr,
+ GET_MODE_SIZE (SImode)));
+
+ /* tmp1 is aligned, OK to load. */
+ emit_move_insn (tmp1, addr1);
+ emit_move_insn (s1_addr, plus_constant (Pmode, s1_addr,
+ GET_MODE_SIZE (SImode)));
+
+ /* Is there a 0 byte ? */
+ emit_insn (gen_andsi3 (tmp3, tmp2, tmp1));
+
+ emit_insn (gen_cmpstr_t (tmp0, tmp3));
+ jump = emit_jump_insn (gen_branch_true (L_end_loop_long));
+ add_int_reg_note (jump, REG_BR_PROB, prob_unlikely);
+
+ emit_insn (gen_cmpeqsi_t (tmp1, tmp2));
+ jump = emit_jump_insn (gen_branch_false (L_end_loop_long));
+ add_int_reg_note (jump, REG_BR_PROB, prob_unlikely);
+
+ if (TARGET_SH2)
+ emit_insn (gen_dect (lenw, lenw));
+ else
+ {
+ emit_insn (gen_addsi3 (lenw, lenw, GEN_INT (-1)));
+ emit_insn (gen_tstsi_t (lenw, lenw));
+ }
+
+ jump = emit_jump_insn (gen_branch_false (L_loop_long));
+ add_int_reg_note (jump, REG_BR_PROB, prob_likely);
+
+ int sbytes = bytes % 4;
+
+ /* end loop. Reached max iterations. */
+ if (sbytes == 0)
+ {
+ jump = emit_jump_insn (gen_jump_compact (L_return));
+ emit_barrier_after (jump);
+ }
+ else
+ {
+ /* Remaining bytes to check. */
+
+ addr1 = adjust_automodify_address (addr1, QImode, s1_addr, 0);
+ addr2 = adjust_automodify_address (addr2, QImode, s2_addr, 0);
+
+ while (sbytes--)
+ {
+ emit_insn (gen_extendqisi2 (tmp1, addr1));
+ emit_insn (gen_extendqisi2 (tmp2, addr2));
+
+ emit_insn (gen_cmpeqsi_t (tmp2, const0_rtx));
+ jump = emit_jump_insn (gen_branch_true (L_end_loop_byte));
+ add_int_reg_note (jump, REG_BR_PROB, prob_unlikely);
+
+ emit_insn (gen_cmpeqsi_t (tmp1, tmp2));
+ if (flag_delayed_branch)
+ emit_insn (gen_zero_extendqisi2 (tmp2,
+ gen_lowpart (QImode,
+ tmp2)));
+ jump = emit_jump_insn (gen_branch_false (L_end_loop_byte));
+ add_int_reg_note (jump, REG_BR_PROB, prob_unlikely);
+
+ addr1 = adjust_address (addr1, QImode,
+ GET_MODE_SIZE (QImode));
+ addr2 = adjust_address (addr2, QImode,
+ GET_MODE_SIZE (QImode));
+ }
+
+ jump = emit_jump_insn (gen_jump_compact( L_end_loop_byte));
+ emit_barrier_after (jump);
+ }
+
+ emit_label (L_end_loop_long);
+
+ /* Found last word. Restart it byte per byte. */
+
+ emit_move_insn (s1_addr, plus_constant (Pmode, s1_addr,
+ -GET_MODE_SIZE (SImode)));
+ emit_move_insn (s2_addr, plus_constant (Pmode, s2_addr,
+ -GET_MODE_SIZE (SImode)));
+
+ /* fall thru. */
+ }
addr1 = adjust_automodify_address (addr1, QImode, s1_addr, 0);
addr2 = adjust_automodify_address (addr2, QImode, s2_addr, 0);
while (bytes--)
- {
- emit_insn (gen_extendqisi2 (tmp1, addr1));
- emit_insn (gen_extendqisi2 (tmp2, addr2));
-
- emit_insn (gen_cmpeqsi_t (tmp2, const0_rtx));
- jump = emit_jump_insn (gen_branch_true (L_end_loop_byte));
- add_int_reg_note (jump, REG_BR_PROB, prob_unlikely);
-
- emit_insn (gen_cmpeqsi_t (tmp1, tmp2));
- if (flag_delayed_branch)
- emit_insn (gen_zero_extendqisi2 (tmp2,
- gen_lowpart (QImode, tmp2)));
- jump = emit_jump_insn (gen_branch_false (L_end_loop_byte));
- add_int_reg_note (jump, REG_BR_PROB, prob_unlikely);
-
- addr1 = adjust_address (addr1, QImode, GET_MODE_SIZE (QImode));
- addr2 = adjust_address (addr2, QImode, GET_MODE_SIZE (QImode));
- }
+ {
+ emit_insn (gen_extendqisi2 (tmp1, addr1));
+ emit_insn (gen_extendqisi2 (tmp2, addr2));
+
+ emit_insn (gen_cmpeqsi_t (tmp2, const0_rtx));
+ jump = emit_jump_insn (gen_branch_true (L_end_loop_byte));
+ add_int_reg_note (jump, REG_BR_PROB, prob_unlikely);
+
+ emit_insn (gen_cmpeqsi_t (tmp1, tmp2));
+ if (flag_delayed_branch)
+ emit_insn (gen_zero_extendqisi2 (tmp2,
+ gen_lowpart (QImode, tmp2)));
+ jump = emit_jump_insn (gen_branch_false (L_end_loop_byte));
+ add_int_reg_note (jump, REG_BR_PROB, prob_unlikely);
+
+ addr1 = adjust_address (addr1, QImode, GET_MODE_SIZE (QImode));
+ addr2 = adjust_address (addr2, QImode, GET_MODE_SIZE (QImode));
+ }
jump = emit_jump_insn (gen_jump_compact( L_end_loop_byte));
emit_barrier_after (jump);
return true;
}
-/* Emit code to perform a strlen
+/* Emit code to perform a strlen.
OPERANDS[0] is the destination.
OPERANDS[1] is the string.
return true;
}
-/* Emit code to perform a memset
+/* Emit code to perform a memset.
OPERANDS[0] is the destination.
OPERANDS[1] is the size;
rtx dest_addr = copy_addr_to_reg (XEXP (dest, 0));
rtx val = force_reg (SImode, operands[2]);
int align = INTVAL (operands[3]);
- int count = 0;
rtx len = force_reg (SImode, operands[1]);
if (! CONST_INT_P (operands[1]))
return;
- count = INTVAL (operands[1]);
+ int count = INTVAL (operands[1]);
if (CONST_INT_P (operands[2])
&& (INTVAL (operands[2]) == 0 || INTVAL (operands[2]) == -1) && count > 8)
rtx lenw = gen_reg_rtx (SImode);
if (align < 4)
- {
- emit_insn (gen_tstsi_t (GEN_INT (3), dest_addr));
- jump = emit_jump_insn (gen_branch_false (L_loop_byte));
- add_int_reg_note (jump, REG_BR_PROB, prob_likely);
- }
+ {
+ emit_insn (gen_tstsi_t (GEN_INT (3), dest_addr));
+ jump = emit_jump_insn (gen_branch_false (L_loop_byte));
+ add_int_reg_note (jump, REG_BR_PROB, prob_likely);
+ }
- /* word count. Do we have iterations ? */
+ /* word count. Do we have iterations ? */
emit_insn (gen_lshrsi3 (lenw, len, GEN_INT (2)));
dest = adjust_automodify_address (dest, SImode, dest_addr, 0);
if (TARGET_SH2)
emit_insn (gen_dect (lenw, lenw));
else
- {
- emit_insn (gen_addsi3 (lenw, lenw, GEN_INT (-1)));
- emit_insn (gen_tstsi_t (lenw, lenw));
- }
+ {
+ emit_insn (gen_addsi3 (lenw, lenw, GEN_INT (-1)));
+ emit_insn (gen_tstsi_t (lenw, lenw));
+ }
emit_move_insn (dest, val);
emit_move_insn (dest_addr, plus_constant (Pmode, dest_addr,
- GET_MODE_SIZE (SImode)));
+ GET_MODE_SIZE (SImode)));
jump = emit_jump_insn (gen_branch_false (L_loop_word));
val = gen_lowpart (QImode, val);
while (count--)
- {
- emit_move_insn (dest, val);
- emit_move_insn (dest_addr, plus_constant (Pmode, dest_addr,
- GET_MODE_SIZE (QImode)));
- }
+ {
+ emit_move_insn (dest, val);
+ emit_move_insn (dest_addr, plus_constant (Pmode, dest_addr,
+ GET_MODE_SIZE (QImode)));
+ }
jump = emit_jump_insn (gen_jump_compact (L_return));
emit_barrier_after (jump);
add_int_reg_note (jump, REG_BR_PROB, prob_likely);
emit_label (L_return);
-
- return;
}
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
+#include <sstream>
+#include <vector>
+#include <algorithm>
+
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "pass_manager.h"
#include "context.h"
-#include <sstream>
-#include <vector>
-#include <algorithm>
-
int code_for_indirect_jump_scratch = CODE_FOR_indirect_jump_scratch;
/* These are some macros to abstract register modes. */
% SH_MIN_ALIGN_FOR_CALLEE_COPY == 0));
}
+/* Round a register number up to a proper boundary for an arg of mode
+ MODE.
+ The SH doesn't care about double alignment, so we only
+ round doubles to even regs when asked to explicitly. */
+static int
+sh_round_reg (const CUMULATIVE_ARGS& cum, machine_mode mode)
+{
+ /* FIXME: This used to be a macro and has been copy pasted into this
+ function as is. Make this more readable. */
+ return
+ (((TARGET_ALIGN_DOUBLE
+ || ((TARGET_SH4 || TARGET_SH2A_DOUBLE)
+ && (mode == DFmode || mode == DCmode)
+ && cum.arg_count[(int) SH_ARG_FLOAT] < NPARM_REGS (mode)))
+ && GET_MODE_UNIT_SIZE (mode) > UNITS_PER_WORD)
+ ? (cum.arg_count[(int) GET_SH_ARG_CLASS (mode)]
+ + (cum.arg_count[(int) GET_SH_ARG_CLASS (mode)] & 1))
+ : cum.arg_count[(int) GET_SH_ARG_CLASS (mode)]);
+}
+
+/* Return true if arg of the specified mode should be be passed in a register
+ or false otherwise. */
+static bool
+sh_pass_in_reg_p (const CUMULATIVE_ARGS& cum, machine_mode mode,
+ const_tree type)
+{
+ /* FIXME: This used to be a macro and has been copy pasted into this
+ function as is. Make this more readable. */
+ return
+ ((type == 0
+ || (! TREE_ADDRESSABLE (type)
+ && (! (TARGET_HITACHI || cum.renesas_abi)
+ || ! (AGGREGATE_TYPE_P (type)
+ || (!TARGET_FPU_ANY
+ && (GET_MODE_CLASS (mode) == MODE_FLOAT
+ && GET_MODE_SIZE (mode) > GET_MODE_SIZE (SFmode)))))))
+ && ! cum.force_mem
+ && (TARGET_SH2E
+ ? ((mode) == BLKmode
+ ? ((cum.arg_count[(int) SH_ARG_INT] * UNITS_PER_WORD
+ + int_size_in_bytes (type))
+ <= NPARM_REGS (SImode) * UNITS_PER_WORD)
+ : ((sh_round_reg (cum, mode)
+ + HARD_REGNO_NREGS (BASE_ARG_REG (mode), mode))
+ <= NPARM_REGS (mode)))
+ : sh_round_reg (cum, mode) < NPARM_REGS (mode)));
+}
+
static int
sh_arg_partial_bytes (cumulative_args_t cum_v, enum machine_mode mode,
tree type, bool named ATTRIBUTE_UNUSED)
int words = 0;
if (!TARGET_SH5
- && PASS_IN_REG_P (*cum, mode, type)
+ && sh_pass_in_reg_p (*cum, mode, type)
&& !(TARGET_SH4 || TARGET_SH2A_DOUBLE)
- && (ROUND_REG (*cum, mode)
+ && (sh_round_reg (*cum, mode)
+ (mode != BLKmode
- ? ROUND_ADVANCE (GET_MODE_SIZE (mode))
- : ROUND_ADVANCE (int_size_in_bytes (type)))
+ ? CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD)
+ : CEIL (int_size_in_bytes (type), UNITS_PER_WORD))
> NPARM_REGS (mode)))
- words = NPARM_REGS (mode) - ROUND_REG (*cum, mode);
+ words = NPARM_REGS (mode) - sh_round_reg (*cum, mode);
else if (!TARGET_SHCOMPACT
&& SH5_WOULD_BE_PARTIAL_NREGS (*cum, mode, type, named))
return GEN_INT (ca->renesas_abi ? 1 : 0);
if (! TARGET_SH5
- && PASS_IN_REG_P (*ca, mode, type)
+ && sh_pass_in_reg_p (*ca, mode, type)
&& (named || ! (TARGET_HITACHI || ca->renesas_abi)))
{
int regno;
if (mode == SCmode && TARGET_SH4 && TARGET_LITTLE_ENDIAN
- && (! FUNCTION_ARG_SCmode_WART || (ROUND_REG (*ca, mode) & 1)))
+ && (! FUNCTION_ARG_SCmode_WART || (sh_round_reg (*ca, mode) & 1)))
{
rtx r1 = gen_rtx_EXPR_LIST (VOIDmode,
gen_rtx_REG (SFmode,
BASE_ARG_REG (mode)
- + (ROUND_REG (*ca, mode) ^ 1)),
+ + (sh_round_reg (*ca, mode) ^ 1)),
const0_rtx);
rtx r2 = gen_rtx_EXPR_LIST (VOIDmode,
gen_rtx_REG (SFmode,
BASE_ARG_REG (mode)
- + ((ROUND_REG (*ca, mode) + 1) ^ 1)),
+ + ((sh_round_reg (*ca, mode) + 1) ^ 1)),
GEN_INT (4));
return gen_rtx_PARALLEL(SCmode, gen_rtvec(2, r1, r2));
}
&& mode == SFmode)
return gen_rtx_REG (mode, ca->free_single_fp_reg);
- regno = (BASE_ARG_REG (mode) + ROUND_REG (*ca, mode))
+ regno = (BASE_ARG_REG (mode) + sh_round_reg (*ca, mode))
^ (mode == SFmode && TARGET_SH4
&& TARGET_LITTLE_ENDIAN
&& ! TARGET_HITACHI && ! ca->renesas_abi);
register, because the next SF value will use it, and not the
SF that follows the DF. */
if (mode == DFmode
- && ROUND_REG (*ca, DFmode) != ROUND_REG (*ca, SFmode))
+ && sh_round_reg (*ca, DFmode) != sh_round_reg (*ca, SFmode))
{
- ca->free_single_fp_reg = (ROUND_REG (*ca, SFmode)
+ ca->free_single_fp_reg = (sh_round_reg (*ca, SFmode)
+ BASE_ARG_REG (mode));
}
}
if (! ((TARGET_SH4 || TARGET_SH2A) || ca->renesas_abi)
- || PASS_IN_REG_P (*ca, mode, type))
+ || sh_pass_in_reg_p (*ca, mode, type))
(ca->arg_count[(int) GET_SH_ARG_CLASS (mode)]
- = (ROUND_REG (*ca, mode)
+ = (sh_round_reg (*ca, mode)
+ (mode == BLKmode
- ? ROUND_ADVANCE (int_size_in_bytes (type))
- : ROUND_ADVANCE (GET_MODE_SIZE (mode)))));
+ ? CEIL (int_size_in_bytes (type), UNITS_PER_WORD)
+ : CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD))));
}
/* The Renesas calling convention doesn't quite fit into this scheme since
{
int named_parm_regs, anon_parm_regs;
- named_parm_regs = (ROUND_REG (*get_cumulative_args (ca), mode)
+ named_parm_regs = (sh_round_reg (*get_cumulative_args (ca), mode)
+ (mode == BLKmode
- ? ROUND_ADVANCE (int_size_in_bytes (type))
- : ROUND_ADVANCE (GET_MODE_SIZE (mode))));
+ ? CEIL (int_size_in_bytes (type), UNITS_PER_WORD)
+ : CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD)));
anon_parm_regs = NPARM_REGS (SImode) - named_parm_regs;
if (anon_parm_regs > 0)
*pretend_arg_size = anon_parm_regs * 4;
#define SUBTARGET_ASM_RELAX_SPEC "%{m4*:-isa=sh4-up}"
#endif
+/* Define which ISA type to pass to the assembler.
+ For SH4 we pass SH4A to allow using some instructions that are available
+ on some SH4 variants, but officially are part of the SH4A ISA. */
#define SH_ASM_SPEC \
"%(subtarget_asm_endian_spec) %{mrelax:-relax %(subtarget_asm_relax_spec)} \
%(subtarget_asm_isa_spec) %(subtarget_asm_spec) \
+%{m1:--isa=sh} \
+%{m2:--isa=sh2} \
+%{m2e:--isa=sh2e} \
+%{m3:--isa=sh3} \
+%{m3e:--isa=sh3e} \
+%{m4:--isa=sh4a} \
+%{m4-single:--isa=sh4a} \
+%{m4-single-only:--isa=sh4a} \
+%{m4-nofpu:--isa=sh4a-nofpu} \
+%{m4a:--isa=sh4a} \
+%{m4a-single:--isa=sh4a} \
+%{m4a-single-only:--isa=sh4a} \
+%{m4a-nofpu:--isa=sh4a-nofpu} \
%{m2a:--isa=sh2a} \
%{m2a-single:--isa=sh2a} \
%{m2a-single-only:--isa=sh2a} \
|| GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT) \
? SH_ARG_FLOAT : SH_ARG_INT)
-#define ROUND_ADVANCE(SIZE) \
- (((SIZE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-
-/* Round a register number up to a proper boundary for an arg of mode
- MODE.
-
- The SH doesn't care about double alignment, so we only
- round doubles to even regs when asked to explicitly. */
-#define ROUND_REG(CUM, MODE) \
- (((TARGET_ALIGN_DOUBLE \
- || ((TARGET_SH4 || TARGET_SH2A_DOUBLE) \
- && ((MODE) == DFmode || (MODE) == DCmode) \
- && (CUM).arg_count[(int) SH_ARG_FLOAT] < NPARM_REGS (MODE))) \
- && GET_MODE_UNIT_SIZE ((MODE)) > UNITS_PER_WORD) \
- ? ((CUM).arg_count[(int) GET_SH_ARG_CLASS (MODE)] \
- + ((CUM).arg_count[(int) GET_SH_ARG_CLASS (MODE)] & 1)) \
- : (CUM).arg_count[(int) GET_SH_ARG_CLASS (MODE)])
-
/* Initialize a variable CUM of type CUMULATIVE_ARGS
for a call to a function whose data type is FNTYPE.
For a library call, FNTYPE is 0.
#define INIT_CUMULATIVE_LIBCALL_ARGS(CUM, MODE, LIBNAME) \
sh_init_cumulative_args (& (CUM), NULL_TREE, (LIBNAME), NULL_TREE, 0, (MODE))
-/* Return boolean indicating arg of mode MODE will be passed in a reg.
- This macro is only used in this file. */
-#define PASS_IN_REG_P(CUM, MODE, TYPE) \
- (((TYPE) == 0 \
- || (! TREE_ADDRESSABLE ((TYPE)) \
- && (! (TARGET_HITACHI || (CUM).renesas_abi) \
- || ! (AGGREGATE_TYPE_P (TYPE) \
- || (!TARGET_FPU_ANY \
- && (GET_MODE_CLASS (MODE) == MODE_FLOAT \
- && GET_MODE_SIZE (MODE) > GET_MODE_SIZE (SFmode))))))) \
- && ! (CUM).force_mem \
- && (TARGET_SH2E \
- ? ((MODE) == BLKmode \
- ? (((CUM).arg_count[(int) SH_ARG_INT] * UNITS_PER_WORD \
- + int_size_in_bytes (TYPE)) \
- <= NPARM_REGS (SImode) * UNITS_PER_WORD) \
- : ((ROUND_REG((CUM), (MODE)) \
- + HARD_REGNO_NREGS (BASE_ARG_REG (MODE), (MODE))) \
- <= NPARM_REGS (MODE))) \
- : ROUND_REG ((CUM), (MODE)) < NPARM_REGS (MODE)))
-
/* By accident we got stuck with passing SCmode on SH4 little endian
in two registers that are nominally successive - which is different from
two single SFmode values, where we take endianness translation into
public:
sh_optimize_sett_clrt (gcc::context* ctx, const char* name);
virtual ~sh_optimize_sett_clrt (void);
- virtual bool gate (function *);
- virtual unsigned int execute (void);
+ virtual bool gate (function*);
+ virtual unsigned int execute (function* fun);
private:
static const pass_data default_pass_data;
}
bool
-sh_optimize_sett_clrt::gate (function *)
+sh_optimize_sett_clrt::gate (function*)
{
return optimize > 0;
}
unsigned int
-sh_optimize_sett_clrt::execute (void)
+sh_optimize_sett_clrt::execute (function* fun)
{
unsigned int ccr0 = INVALID_REGNUM;
unsigned int ccr1 = INVALID_REGNUM;
// Look for insns that set the ccreg to a constant value and see if it can
// be optimized.
basic_block bb;
- FOR_EACH_BB_REVERSE_FN (bb, cfun)
+ FOR_EACH_BB_REVERSE_FN (bb, fun)
for (rtx next_i, i = NEXT_INSN (BB_HEAD (bb));
i != NULL_RTX && i != BB_END (bb); i = next_i)
{
+2014-05-03 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58582
+ * decl.c (grokfndecl): Check duplicate_decls return value for
+ error_mark_node.
+ * pt.c (instantiate_decl): A deleted function is defined.
+
+2014-05-02 Jason Merrill <jason@redhat.com>
+
+ * decl2.c (vague_linkage_p): Local statics have vague linkage.
+
+ PR c++/60992
+ * lambda.c (lambda_capture_field_type): Wrap anything dependent
+ other than 'this'.
+ (add_capture): Check for VLA before calling it.
+ * semantics.c (is_this_parameter): Accept any 'this' parameter, not
+ just the current one. Make non-static.
+ * cp-tree.h: Declare it.
+ * pt.c (tsubst_copy) [VAR_DECL]: Also build a new VAR_DECL if
+ the operand was static or constant.
+
+2014-05-02 Marek Polacek <polacek@redhat.com>
+
+ * typeck.c (maybe_warn_about_returning_address_of_local): Separate
+ warning_at calls.
+
+2014-05-01 Marek Polacek <polacek@redhat.com>
+
+ PR c/43395
+ * typeck.c (maybe_warn_about_returning_address_of_local): Distinguish
+ between label and variable when warning about returning local address.
+
2014-04-30 Jason Merrill <jason@redhat.com>
PR c++/60980
extern bool reduced_constant_expression_p (tree);
extern void explain_invalid_constexpr_fn (tree);
extern vec<tree> cx_error_context (void);
+extern bool is_this_parameter (tree);
enum {
BCS_NO_SCOPE = 1,
decl, ctype);
return NULL_TREE;
}
+ if (ok == error_mark_node)
+ return NULL_TREE;
return old_decl;
}
}
/* Unfortunately, import_export_decl has not always been called
before the function is processed, so we cannot simply check
DECL_COMDAT. */
- return (DECL_COMDAT (decl)
- || (((TREE_CODE (decl) == FUNCTION_DECL
- && DECL_DECLARED_INLINE_P (decl))
- || (DECL_LANG_SPECIFIC (decl)
- && DECL_TEMPLATE_INSTANTIATION (decl)))
- && TREE_PUBLIC (decl)));
+ if (DECL_COMDAT (decl)
+ || (((TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_DECLARED_INLINE_P (decl))
+ || (DECL_LANG_SPECIFIC (decl)
+ && DECL_TEMPLATE_INSTANTIATION (decl)))
+ && TREE_PUBLIC (decl)))
+ return true;
+ else if (DECL_FUNCTION_SCOPE_P (decl))
+ /* A local static in an inline effectively has vague linkage. */
+ return (TREE_STATIC (decl)
+ && vague_linkage_p (DECL_CONTEXT (decl)));
+ else
+ return false;
}
/* Determine whether or not we want to specifically import or export CTYPE,
}
else
type = non_reference (unlowered_expr_type (expr));
- if (!type || WILDCARD_TYPE_P (type) || type_uses_auto (type)
- || DECL_PACK_P (expr))
+ if (type_dependent_expression_p (expr)
+ && !is_this_parameter (tree_strip_nop_conversions (expr)))
{
type = cxx_make_type (DECLTYPE_TYPE);
DECLTYPE_TYPE_EXPR (type) = expr;
if (TREE_CODE (initializer) == TREE_LIST)
initializer = build_x_compound_expr_from_list (initializer, ELK_INIT,
tf_warning_or_error);
- type = lambda_capture_field_type (initializer, explicit_init_p);
+ type = TREE_TYPE (initializer);
if (array_of_runtime_bound_p (type))
{
vla = true;
"variable size", TREE_TYPE (type));
type = error_mark_node;
}
- else if (by_reference_p)
+ else
{
- type = build_reference_type (type);
- if (!real_lvalue_p (initializer))
- error ("cannot capture %qE by reference", initializer);
+ type = lambda_capture_field_type (initializer, explicit_init_p);
+ if (by_reference_p)
+ {
+ type = build_reference_type (type);
+ if (!real_lvalue_p (initializer))
+ error ("cannot capture %qE by reference", initializer);
+ }
+ else
+ /* Capture by copy requires a complete type. */
+ type = complete_type (type);
}
- else
- /* Capture by copy requires a complete type. */
- type = complete_type (type);
/* Add __ to the beginning of the field name so that user code
won't find the field with name lookup. We can't just leave the name
}
else
{
- /* This can happen for a variable used in a late-specified
- return type of a local lambda. Just make a dummy decl
- since it's only used for its type. */
- if (cp_unevaluated_operand)
- return tsubst_decl (t, args, complain);
- gcc_assert (errorcount || sorrycount);
- return error_mark_node;
+ /* This can happen for a variable used in a
+ late-specified return type of a local lambda, or for a
+ local static or constant. Building a new VAR_DECL
+ should be OK in all those cases. */
+ r = tsubst_decl (t, args, complain);
+ if (decl_constant_var_p (r))
+ /* A use of a local constant must decay to its value. */
+ return integral_constant_value (r);
+ gcc_assert (cp_unevaluated_operand || TREE_STATIC (r)
+ || errorcount || sorrycount);
+ return r;
}
}
}
if (TREE_CODE (d) == FUNCTION_DECL)
pattern_defined = (DECL_SAVED_TREE (code_pattern) != NULL_TREE
- || DECL_DEFAULTED_OUTSIDE_CLASS_P (code_pattern));
+ || DECL_DEFAULTED_OUTSIDE_CLASS_P (code_pattern)
+ || DECL_DELETED_FN (code_pattern));
else
pattern_defined = ! DECL_IN_AGGR_P (code_pattern);
tf_warning_or_error, tmpl,
/*integral_constant_expression_p=*/false);
- /* Set the current input_location to the end of the function
- so that finish_function knows where we are. */
- input_location
- = DECL_STRUCT_FUNCTION (code_pattern)->function_end_locus;
-
- /* Remember if we saw an infinite loop in the template. */
- current_function_infinite_loop
- = DECL_STRUCT_FUNCTION (code_pattern)->language->infinite_loop;
+ if (DECL_STRUCT_FUNCTION (code_pattern))
+ {
+ /* Set the current input_location to the end of the function
+ so that finish_function knows where we are. */
+ input_location
+ = DECL_STRUCT_FUNCTION (code_pattern)->function_end_locus;
+
+ /* Remember if we saw an infinite loop in the template. */
+ current_function_infinite_loop
+ = DECL_STRUCT_FUNCTION (code_pattern)->language->infinite_loop;
+ }
}
/* We don't need the local specializations any more. */
/* Return true if T designates the implied `this' parameter. */
-static inline bool
+bool
is_this_parameter (tree t)
{
- return t == current_class_ptr;
+ return (TREE_CODE (t) == PARM_DECL
+ && DECL_NAME (t) == this_identifier);
}
/* We have an expression tree T that represents a call, either CALL_EXPR
if (TREE_CODE (valtype) == REFERENCE_TYPE)
warning (OPT_Wreturn_local_addr, "reference to local variable %q+D returned",
whats_returned);
- else
- warning (OPT_Wreturn_local_addr, "address of local variable %q+D returned",
+ else if (TREE_CODE (whats_returned) == LABEL_DECL)
+ warning (OPT_Wreturn_local_addr, "address of label %q+D returned",
whats_returned);
+ else
+ warning (OPT_Wreturn_local_addr, "address of local variable %q+D "
+ "returned", whats_returned);
return;
}
}
#define LOCAL_REGNO(REGNO) 0
#endif
+#ifndef HONOR_REG_ALLOC_ORDER
+#define HONOR_REG_ALLOC_ORDER 0
+#endif
+
/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
the stack pointer does not matter. The value is tested only in
functions that have frame pointers. */
-Wchar-subscripts -Wclobbered -Wcomment -Wconditionally-supported @gol
-Wconversion -Wcoverage-mismatch -Wdate-time -Wdelete-incomplete -Wno-cpp @gol
-Wno-deprecated -Wno-deprecated-declarations -Wdisabled-optimization @gol
+-Wno-discarded-qualifiers @gol
-Wno-div-by-zero -Wdouble-promotion -Wempty-body -Wenum-compare @gol
-Wno-endif-labels -Werror -Werror=* @gol
-Wfatal-errors -Wfloat-equal -Wformat -Wformat=2 @gol
(default for @option{-O2} and above). It warns about subscripts to arrays
that are always out of bounds. This warning is enabled by @option{-Wall}.
+@item -Wno-discarded-qualifiers
+@opindex Wno-discarded-qualifiers
+@opindex Wdiscarded-qualifiers
+Do not warn if type qualifiers on pointers are being discarded.
+Typically, the compiler will warn if a @code{const char *} variable is
+passed to a function that takes @code{char *} parameter. This option
+can be used to suppress such a warning. This warning is only supported
+for C.
+
@item -Wno-div-by-zero
@opindex Wno-div-by-zero
@opindex Wdiv-by-zero
@option{-fsanitize=undefined} gives a diagnostic message.
This currently works only for the C family of languages.
+@item -fsanitize=float-divide-by-zero
+@opindex fsanitize=float-divide-by-zero
+
+Detect floating-point division by zero. Unlike other similar options,
+@option{-fsanitize=float-divide-by-zero} is not enabled by
+@option{-fsanitize=undefined}, since floating-point division by zero can
+be a legitimate way of obtaining infinities and NaNs.
+
@item -fsanitize-recover
@opindex fsanitize-recover
By default @option{-fsanitize=undefined} sanitization (and its suboptions
prologue and restoring it in the epilogue. This discourages it from
using call-saved registers. If a machine wants to ensure that IRA
allocates registers in the order given by REG_ALLOC_ORDER even if some
-call-saved registers appear earlier than call-used ones, this macro
-should be defined.
+call-saved registers appear earlier than call-used ones, then define this
+macro as a C expression to nonzero. Default is 0.
@end defmac
@defmac IRA_HARD_REGNO_ADD_COST_MULTIPLIER (@var{regno})
the function prologue. Normally, the profiling code comes after.
@end defmac
+@deftypefn {Target Hook} bool TARGET_KEEP_LEAF_WHEN_PROFILED (void)
+This target hook returns true if the target wants the leaf flag for the current function to stay true even if it calls mcount. This might make sense for targets using the leaf flag only to determine whether a stack frame needs to be generated or not and for which the call to mcount is generated before the function prologue.
+@end deftypefn
+
@node Tail Calls
@subsection Permitting tail calls
@cindex tail calls
prologue and restoring it in the epilogue. This discourages it from
using call-saved registers. If a machine wants to ensure that IRA
allocates registers in the order given by REG_ALLOC_ORDER even if some
-call-saved registers appear earlier than call-used ones, this macro
-should be defined.
+call-saved registers appear earlier than call-used ones, then define this
+macro as a C expression to nonzero. Default is 0.
@end defmac
@defmac IRA_HARD_REGNO_ADD_COST_MULTIPLIER (@var{regno})
the function prologue. Normally, the profiling code comes after.
@end defmac
+@hook TARGET_KEEP_LEAF_WHEN_PROFILED
+
@node Tail Calls
@subsection Permitting tail calls
@cindex tail calls
{
rtx insn;
- if (crtl->profile || profile_arc_flag)
+ /* Some back-ends (e.g. s390) want leaf functions to stay leaf
+ functions even if they call mcount. */
+ if (crtl->profile && !targetm.keep_leaf_when_profiled ())
return 0;
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
&& TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
{
int width = TYPE_PRECISION (type), w;
- bool try_simplify = true;
wide_int c1 = TREE_OPERAND (arg0, 1);
wide_int c2 = arg1;
}
}
- /* If X is a tree of the form (Y * K1) & K2, this might conflict
- with that optimization from the BIT_AND_EXPR optimizations.
- This could end up in an infinite recursion. */
- if (TREE_CODE (TREE_OPERAND (arg0, 0)) == MULT_EXPR
- && TREE_CODE (TREE_OPERAND (TREE_OPERAND (arg0, 0), 1))
- == INTEGER_CST)
- {
- tree t = TREE_OPERAND (TREE_OPERAND (arg0, 0), 1);
- wide_int masked = mask_with_tz (type, c3, t);
-
- try_simplify = (masked != c1);
- }
-
- if (try_simplify && c3 != c1)
+ if (c3 != c1)
return fold_build2_loc (loc, BIT_IOR_EXPR, type,
fold_build2_loc (loc, BIT_AND_EXPR, type,
TREE_OPERAND (arg0, 0),
&& TREE_CODE (arg0) == MULT_EXPR
&& TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
{
- wide_int masked = mask_with_tz (type, arg1, TREE_OPERAND (arg0, 1));
+ wide_int warg1 = arg1;
+ wide_int masked = mask_with_tz (type, warg1, TREE_OPERAND (arg0, 1));
if (masked == 0)
return omit_two_operands_loc (loc, type, build_zero_cst (type),
arg0, arg1);
- else if (masked != arg1)
- return fold_build2_loc (loc, code, type, op0,
- wide_int_to_tree (type, masked));
+ else if (masked != warg1)
+ {
+ /* Avoid the transform if arg1 is a mask of some
+ mode which allows further optimizations. */
+ int pop = wi::popcount (warg1);
+ if (!(pop >= BITS_PER_UNIT
+ && exact_log2 (pop) != -1
+ && wi::mask (pop, false, warg1.get_precision ()) == warg1))
+ return fold_build2_loc (loc, code, type, op0,
+ wide_int_to_tree (type, masked));
+ }
}
/* For constants M and N, if M == (1LL << cst) - 1 && (N & M) == M,
-2014-03-27 Thomas Koenig <tkoenig@gcc.gnu.org>
+2014-04-30 Tobias Burnus <burnus@net-b.de>
+
+ * trans-decl.c (create_function_arglist): Add hidden coarray arguments
+ also for polymorphic coarrays.
+ * trans-expr.c (gfc_conv_procedure_call): Pass hidden coarray arguments
+ also for polymorphic coarrays.
+
+2014-04-30 Tobias Burnus <burnus@net-b.de>
+
+ * resolve.c (resolve_function): Don't do
+ assumed-size check for lcobound/ucobound.
+ * trans-types.c (gfc_build_array_type): Only build an array
+ descriptor with codimensions for allocatable coarrays.
+
+2014-04-30 Tobias Burnus <burnus@net-b.de>
+
+ * gfortran.h (gfc_init_coarray_decl): Remove.
+ * parse.c (translate_all_program_units): Remove call to it.
+ (gfc_parse_file): Update call.
+ * trans.h (gfor_fndecl_caf_this_image,
+ gfor_fndecl_caf_num_images): Add.
+ (gfort_gvar_caf_num_images,
+ gfort_gvar_caf_this_image): Remove.
+ * trans-decl.c (gfor_fndecl_caf_this_image,
+ gfor_fndecl_caf_num_images): Add.
+ (gfort_gvar_caf_num_images,
+ gfort_gvar_caf_this_image): Remove.
+ (gfc_build_builtin_function_decls): Init new decl.
+ (gfc_init_coarray_dec): Remove.
+ (create_main_function): Change calls.
+ * trans-intrinsic.c (trans_this_image, trans_image_index,
+ conv_intrinsic_cobound): Generate call to new library function
+ instead of to a static variable.
+ * trans-stmt.c (gfc_trans_sync): Ditto.
+
+2014-04-30 Tobias Burnus <burnus@net-b.de>
+
+ * trans-expr.c (get_tree_for_caf_expr): Fix handling of polymorphic
+ and derived-type coarrays.
+
+2014-04-27 Thomas Koenig <tkoenig@gcc.gnu.org>
PR fortran/59604
PR fortran/58003
/* trans.c */
void gfc_generate_code (gfc_namespace *);
void gfc_generate_module_code (gfc_namespace *);
-void gfc_init_coarray_decl (bool);
/* trans-intrinsic.c */
bool gfc_inline_intrinsic_function_p (gfc_expr *);
/* Translate all the program units. This could be in a different order
to resolution if there are forward references in the file. */
static void
-translate_all_program_units (gfc_namespace *gfc_global_ns_list,
- bool main_in_tu)
+translate_all_program_units (gfc_namespace *gfc_global_ns_list)
{
int errors;
gfc_current_ns = gfc_global_ns_list;
gfc_get_errors (NULL, &errors);
- /* If the main program is in the translation unit and we have
- -fcoarray=libs, generate the static variables. */
- if (gfc_option.coarray == GFC_FCOARRAY_LIB && main_in_tu)
- gfc_init_coarray_decl (true);
-
/* We first translate all modules to make sure that later parts
of the program can use the decl. Then we translate the nonmodules. */
}
/* Do the translation. */
- translate_all_program_units (gfc_global_ns_list, seen_program);
+ translate_all_program_units (gfc_global_ns_list);
gfc_end_source_files ();
return true;
else if (expr->value.function.actual != NULL
&& expr->value.function.isym != NULL
&& GENERIC_ID != GFC_ISYM_LBOUND
+ && GENERIC_ID != GFC_ISYM_LCOBOUND
+ && GENERIC_ID != GFC_ISYM_UCOBOUND
&& GENERIC_ID != GFC_ISYM_LEN
&& GENERIC_ID != GFC_ISYM_LOC
&& GENERIC_ID != GFC_ISYM_C_LOC
/* Coarray run-time library function decls. */
tree gfor_fndecl_caf_init;
tree gfor_fndecl_caf_finalize;
+tree gfor_fndecl_caf_this_image;
+tree gfor_fndecl_caf_num_images;
tree gfor_fndecl_caf_register;
tree gfor_fndecl_caf_deregister;
tree gfor_fndecl_caf_critical;
tree gfor_fndecl_caf_error_stop;
tree gfor_fndecl_caf_error_stop_str;
-/* Coarray global variables for num_images/this_image. */
-
-tree gfort_gvar_caf_num_images;
-tree gfort_gvar_caf_this_image;
-
/* Math functions. Many other math functions are handled in
trans-intrinsic.c. */
/* Coarrays which are descriptorless or assumed-shape pass with
-fcoarray=lib the token and the offset as hidden arguments. */
- if (f->sym->attr.codimension
- && gfc_option.coarray == GFC_FCOARRAY_LIB
- && !f->sym->attr.allocatable)
+ if (gfc_option.coarray == GFC_FCOARRAY_LIB
+ && ((f->sym->ts.type != BT_CLASS && f->sym->attr.codimension
+ && !f->sym->attr.allocatable)
+ || (f->sym->ts.type == BT_CLASS
+ && CLASS_DATA (f->sym)->attr.codimension
+ && !CLASS_DATA (f->sym)->attr.allocatable)))
{
tree caf_type;
tree token;
gcc_assert (f->sym->backend_decl != NULL_TREE
&& !sym->attr.is_bind_c);
- caf_type = TREE_TYPE (f->sym->backend_decl);
+ caf_type = f->sym->ts.type == BT_CLASS
+ ? TREE_TYPE (CLASS_DATA (f->sym)->backend_decl)
+ : TREE_TYPE (f->sym->backend_decl);
token = build_decl (input_location, PARM_DECL,
create_tmp_var_name ("caf_token"),
build_qualified_type (pvoid_type_node,
TYPE_QUAL_RESTRICT));
- if (f->sym->as->type == AS_ASSUMED_SHAPE)
+ if ((f->sym->ts.type != BT_CLASS
+ && f->sym->as->type != AS_DEFERRED)
+ || (f->sym->ts.type == BT_CLASS
+ && CLASS_DATA (f->sym)->as->type != AS_DEFERRED))
{
gcc_assert (DECL_LANG_SPECIFIC (f->sym->backend_decl) == NULL
|| GFC_DECL_TOKEN (f->sym->backend_decl) == NULL_TREE);
create_tmp_var_name ("caf_offset"),
gfc_array_index_type);
- if (f->sym->as->type == AS_ASSUMED_SHAPE)
+ if ((f->sym->ts.type != BT_CLASS
+ && f->sym->as->type != AS_DEFERRED)
+ || (f->sym->ts.type == BT_CLASS
+ && CLASS_DATA (f->sym)->as->type != AS_DEFERRED))
{
gcc_assert (GFC_DECL_CAF_OFFSET (f->sym->backend_decl)
== NULL_TREE);
gfor_fndecl_caf_finalize = gfc_build_library_function_decl (
get_identifier (PREFIX("caf_finalize")), void_type_node, 0);
+ gfor_fndecl_caf_this_image = gfc_build_library_function_decl (
+ get_identifier (PREFIX("caf_this_image")), integer_type_node,
+ 1, integer_type_node);
+
+ gfor_fndecl_caf_num_images = gfc_build_library_function_decl (
+ get_identifier (PREFIX("caf_num_images")), integer_type_node,
+ 2, integer_type_node, boolean_type_node);
+
gfor_fndecl_caf_register = gfc_build_library_function_decl_with_spec (
get_identifier (PREFIX("caf_register")), "...WWW", pvoid_type_node, 6,
size_type_node, integer_type_node, ppvoid_type_node, pint_type,
}
-/* Generate the _gfortran_caf_this_image and _gfortran_caf_num_images
- global variables for -fcoarray=lib. They are placed into the translation
- unit of the main program. Make sure that in one TU (the one of the main
- program), the first call to gfc_init_coarray_decl is done with true.
- Otherwise, expect link errors. */
-
-void
-gfc_init_coarray_decl (bool main_tu)
-{
- if (gfc_option.coarray != GFC_FCOARRAY_LIB)
- return;
-
- if (gfort_gvar_caf_this_image || gfort_gvar_caf_num_images)
- return;
-
- push_cfun (cfun);
-
- gfort_gvar_caf_this_image
- = build_decl (input_location, VAR_DECL,
- get_identifier (PREFIX("caf_this_image")),
- integer_type_node);
- DECL_ARTIFICIAL (gfort_gvar_caf_this_image) = 1;
- TREE_USED (gfort_gvar_caf_this_image) = 1;
- TREE_PUBLIC (gfort_gvar_caf_this_image) = 1;
- TREE_READONLY (gfort_gvar_caf_this_image) = 0;
-
- if (main_tu)
- TREE_STATIC (gfort_gvar_caf_this_image) = 1;
- else
- DECL_EXTERNAL (gfort_gvar_caf_this_image) = 1;
-
- pushdecl_top_level (gfort_gvar_caf_this_image);
-
- gfort_gvar_caf_num_images
- = build_decl (input_location, VAR_DECL,
- get_identifier (PREFIX("caf_num_images")),
- integer_type_node);
- DECL_ARTIFICIAL (gfort_gvar_caf_num_images) = 1;
- TREE_USED (gfort_gvar_caf_num_images) = 1;
- TREE_PUBLIC (gfort_gvar_caf_num_images) = 1;
- TREE_READONLY (gfort_gvar_caf_num_images) = 0;
-
- if (main_tu)
- TREE_STATIC (gfort_gvar_caf_num_images) = 1;
- else
- DECL_EXTERNAL (gfort_gvar_caf_num_images) = 1;
-
- pushdecl_top_level (gfort_gvar_caf_num_images);
-
- pop_cfun ();
-}
-
-
static void
create_main_function (tree fndecl)
{
/* Call some libgfortran initialization routines, call then MAIN__(). */
- /* Call _gfortran_caf_init (*argc, ***argv, *this_image, *num_images). */
+ /* Call _gfortran_caf_init (*argc, ***argv). */
if (gfc_option.coarray == GFC_FCOARRAY_LIB)
{
tree pint_type, pppchar_type;
pppchar_type
= build_pointer_type (build_pointer_type (pchar_type_node));
- gfc_init_coarray_decl (true);
- tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_init, 4,
+ tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_init, 2,
gfc_build_addr_expr (pint_type, argc),
- gfc_build_addr_expr (pppchar_type, argv),
- gfc_build_addr_expr (pint_type, gfort_gvar_caf_this_image),
- gfc_build_addr_expr (pint_type, gfort_gvar_caf_num_images));
+ gfc_build_addr_expr (pppchar_type, argv));
gfc_add_expr_to_block (&body, tmp);
}
static tree
get_tree_for_caf_expr (gfc_expr *expr)
{
- tree caf_decl = NULL_TREE;
- gfc_ref *ref;
+ tree caf_decl;
+ bool found;
+ gfc_ref *ref;
- gcc_assert (expr && expr->expr_type == EXPR_VARIABLE);
- if (expr->symtree->n.sym->attr.codimension)
- caf_decl = expr->symtree->n.sym->backend_decl;
+ gcc_assert (expr && expr->expr_type == EXPR_VARIABLE);
- for (ref = expr->ref; ref; ref = ref->next)
- if (ref->type == REF_COMPONENT)
- {
+ caf_decl = expr->symtree->n.sym->backend_decl;
+ gcc_assert (caf_decl);
+ if (expr->symtree->n.sym->ts.type == BT_CLASS)
+ caf_decl = gfc_class_data_get (caf_decl);
+ if (expr->symtree->n.sym->attr.codimension)
+ return caf_decl;
+
+ /* The following code assumes that the coarray is a component reachable via
+ only scalar components/variables; the Fortran standard guarantees this. */
+
+ for (ref = expr->ref; ref; ref = ref->next)
+ if (ref->type == REF_COMPONENT)
+ {
gfc_component *comp = ref->u.c.component;
- if (comp->attr.pointer || comp->attr.allocatable)
- caf_decl = NULL_TREE;
- if (comp->attr.codimension)
- caf_decl = comp->backend_decl;
- }
- gcc_assert (caf_decl != NULL_TREE);
- return caf_decl;
+ if (POINTER_TYPE_P (TREE_TYPE (caf_decl)))
+ caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
+ caf_decl = fold_build3_loc (input_location, COMPONENT_REF,
+ TREE_TYPE (comp->backend_decl), caf_decl,
+ comp->backend_decl, NULL_TREE);
+ if (comp->ts.type == BT_CLASS)
+ caf_decl = gfc_class_data_get (caf_decl);
+ if (comp->attr.codimension)
+ {
+ found = true;
+ break;
+ }
+ }
+ gcc_assert (found && caf_decl);
+ return caf_decl;
}
/* For descriptorless coarrays and assumed-shape coarray dummies, we
pass the token and the offset as additional arguments. */
- if (fsym && fsym->attr.codimension
- && gfc_option.coarray == GFC_FCOARRAY_LIB
- && !fsym->attr.allocatable
- && e == NULL)
+ if (fsym && e == NULL && gfc_option.coarray == GFC_FCOARRAY_LIB
+ && ((fsym->ts.type != BT_CLASS && fsym->attr.codimension
+ && !fsym->attr.allocatable)
+ || (fsym->ts.type == BT_CLASS
+ && CLASS_DATA (fsym)->attr.codimension
+ && !CLASS_DATA (fsym)->attr.allocatable)))
{
/* Token and offset. */
vec_safe_push (stringargs, null_pointer_node);
vec_safe_push (stringargs, build_int_cst (gfc_array_index_type, 0));
gcc_assert (fsym->attr.optional);
}
- else if (fsym && fsym->attr.codimension
- && !fsym->attr.allocatable
- && gfc_option.coarray == GFC_FCOARRAY_LIB)
+ else if (fsym && gfc_option.coarray == GFC_FCOARRAY_LIB
+ && ((fsym->ts.type != BT_CLASS && fsym->attr.codimension
+ && !fsym->attr.allocatable)
+ || (fsym->ts.type == BT_CLASS
+ && CLASS_DATA (fsym)->attr.codimension
+ && !CLASS_DATA (fsym)->attr.allocatable)))
{
tree caf_decl, caf_type;
tree offset, tmp2;
tmp = caf_decl;
}
- if (fsym->as->type == AS_ASSUMED_SHAPE
- || (fsym->as->type == AS_ASSUMED_RANK && !fsym->attr.pointer
- && !fsym->attr.allocatable))
+ tmp2 = fsym->ts.type == BT_CLASS
+ ? gfc_class_data_get (parmse.expr) : parmse.expr;
+ if ((fsym->ts.type != BT_CLASS
+ && (fsym->as->type == AS_ASSUMED_SHAPE
+ || fsym->as->type == AS_ASSUMED_RANK))
+ || (fsym->ts.type == BT_CLASS
+ && (CLASS_DATA (fsym)->as->type == AS_ASSUMED_SHAPE
+ || CLASS_DATA (fsym)->as->type == AS_ASSUMED_RANK)))
{
- gcc_assert (POINTER_TYPE_P (TREE_TYPE (parmse.expr)));
- gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE
- (TREE_TYPE (parmse.expr))));
- tmp2 = build_fold_indirect_ref_loc (input_location, parmse.expr);
+ if (fsym->ts.type == BT_CLASS)
+ gcc_assert (!POINTER_TYPE_P (TREE_TYPE (tmp2)));
+ else
+ {
+ gcc_assert (POINTER_TYPE_P (TREE_TYPE (tmp2)));
+ tmp2 = build_fold_indirect_ref_loc (input_location, tmp2);
+ }
+ gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp2)));
tmp2 = gfc_conv_descriptor_data_get (tmp2);
}
- else if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (parmse.expr)))
- tmp2 = gfc_conv_descriptor_data_get (parmse.expr);
+ else if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp2)))
+ tmp2 = gfc_conv_descriptor_data_get (tmp2);
else
{
- gcc_assert (POINTER_TYPE_P (TREE_TYPE (parmse.expr)));
- tmp2 = parmse.expr;
+ gcc_assert (POINTER_TYPE_P (TREE_TYPE (tmp2)));
}
tmp = fold_build2_loc (input_location, MINUS_EXPR,
/* The case -fcoarray=single is handled elsewhere. */
gcc_assert (gfc_option.coarray != GFC_FCOARRAY_SINGLE);
- gfc_init_coarray_decl (false);
-
/* Argument-free version: THIS_IMAGE(). */
if (expr->value.function.actual->expr == NULL)
{
+ tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_this_image, 1,
+ integer_zero_node);
se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind),
- gfort_gvar_caf_this_image);
+ tmp);
return;
}
*/
/* this_image () - 1. */
- tmp = fold_convert (type, gfort_gvar_caf_this_image);
- tmp = fold_build2_loc (input_location, MINUS_EXPR, type, tmp,
- build_int_cst (type, 1));
+ tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_this_image, 1,
+ integer_zero_node);
+ tmp = fold_build2_loc (input_location, MINUS_EXPR, type,
+ fold_convert (type, tmp), build_int_cst (type, 1));
if (corank == 1)
{
/* sub(1) = m + lcobound(corank). */
num_images = build_int_cst (type, 1);
else
{
- gfc_init_coarray_decl (false);
- num_images = fold_convert (type, gfort_gvar_caf_num_images);
+ tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images, 2,
+ integer_zero_node,
+ build_int_cst (integer_type_node, -1));
+ num_images = fold_convert (type, tmp);
}
tmp = gfc_create_var (type, NULL);
static void
trans_num_images (gfc_se * se)
{
- gfc_init_coarray_decl (false);
- se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind),
- gfort_gvar_caf_num_images);
+ tree tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images, 2,
+ integer_zero_node,
+ build_int_cst (integer_type_node, -1));
+ se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp);
}
{
tree cosize;
- gfc_init_coarray_decl (false);
cosize = gfc_conv_descriptor_cosize (desc, arg->expr->rank, corank);
-
+ tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
+ 2, integer_zero_node,
+ build_int_cst (integer_type_node, -1));
tmp = fold_build2_loc (input_location, MINUS_EXPR,
gfc_array_index_type,
- fold_convert (gfc_array_index_type,
- gfort_gvar_caf_num_images),
+ fold_convert (gfc_array_index_type, tmp),
build_int_cst (gfc_array_index_type, 1));
tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
gfc_array_index_type, tmp,
else if (gfc_option.coarray != GFC_FCOARRAY_SINGLE)
{
/* ubound = lbound + num_images() - 1. */
- gfc_init_coarray_decl (false);
+ tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
+ 2, integer_zero_node,
+ build_int_cst (integer_type_node, -1));
tmp = fold_build2_loc (input_location, MINUS_EXPR,
gfc_array_index_type,
- fold_convert (gfc_array_index_type,
- gfort_gvar_caf_num_images),
+ fold_convert (gfc_array_index_type, tmp),
build_int_cst (gfc_array_index_type, 1));
resbound = fold_build2_loc (input_location, PLUS_EXPR,
gfc_array_index_type, resbound, tmp);
else
{
tree cond2;
+ tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
+ 2, integer_zero_node,
+ build_int_cst (integer_type_node, -1));
cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
- images, gfort_gvar_caf_num_images);
+ images, tmp);
cond2 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
images,
build_int_cst (TREE_TYPE (images), 1));
{
tree lbound[GFC_MAX_DIMENSIONS];
tree ubound[GFC_MAX_DIMENSIONS];
- int n;
+ int n, corank;
+
+ /* Assumed-shape arrays do not have codimension information stored in the
+ descriptor. */
+ corank = as->corank;
+ if (as->type == AS_ASSUMED_SHAPE ||
+ (as->type == AS_ASSUMED_RANK && akind == GFC_ARRAY_ALLOCATABLE))
+ corank = 0;
if (as->type == AS_ASSUMED_RANK)
for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
ubound[n] = gfc_conv_array_bound (as->upper[n]);
}
- for (n = as->rank; n < as->rank + as->corank; n++)
+ for (n = as->rank; n < as->rank + corank; n++)
{
if (as->type != AS_DEFERRED && as->lower[n] == NULL)
lbound[n] = gfc_index_one_node;
else
lbound[n] = gfc_conv_array_bound (as->lower[n]);
- if (n < as->rank + as->corank - 1)
+ if (n < as->rank + corank - 1)
ubound[n] = gfc_conv_array_bound (as->upper[n]);
}
: GFC_ARRAY_ASSUMED_RANK;
return gfc_get_array_type_bounds (type, as->rank == -1
? GFC_MAX_DIMENSIONS : as->rank,
- as->corank, lbound,
+ corank, lbound,
ubound, 0, akind, restricted);
}
\f
/* Coarray run-time library function decls. */
extern GTY(()) tree gfor_fndecl_caf_init;
extern GTY(()) tree gfor_fndecl_caf_finalize;
+extern GTY(()) tree gfor_fndecl_caf_this_image;
+extern GTY(()) tree gfor_fndecl_caf_num_images;
extern GTY(()) tree gfor_fndecl_caf_register;
extern GTY(()) tree gfor_fndecl_caf_deregister;
extern GTY(()) tree gfor_fndecl_caf_critical;
extern GTY(()) tree gfor_fndecl_caf_error_stop;
extern GTY(()) tree gfor_fndecl_caf_error_stop_str;
-/* Coarray global variables for num_images/this_image. */
-extern GTY(()) tree gfort_gvar_caf_num_images;
-extern GTY(()) tree gfort_gvar_caf_this_image;
-
/* Math functions. Many other math functions are handled in
trans-intrinsic.c. */
OMP_CLAUSE_CHAIN (clause) = nc;
}
}
+ if (code == OMP_CLAUSE_FIRSTPRIVATE && (flags & GOVD_LASTPRIVATE) != 0)
+ {
+ tree nc = build_omp_clause (input_location, OMP_CLAUSE_LASTPRIVATE);
+ OMP_CLAUSE_DECL (nc) = decl;
+ OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (nc) = 1;
+ OMP_CLAUSE_CHAIN (nc) = *list_p;
+ OMP_CLAUSE_CHAIN (clause) = nc;
+ lang_hooks.decls.omp_finish_clause (nc);
+ }
*list_p = clause;
lang_hooks.decls.omp_finish_clause (clause);
-
return 0;
}
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
&& ctx->outer_context
&& !(OMP_CLAUSE_LINEAR_NO_COPYIN (c)
- && OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
- && !is_global_var (decl))
+ && OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
{
- if (ctx->outer_context->region_type == ORT_COMBINED_PARALLEL)
+ if (ctx->outer_context->combined_loop
+ && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
{
n = splay_tree_lookup (ctx->outer_context->variables,
(splay_tree_key) decl);
if (n == NULL
|| (n->value & GOVD_DATA_SHARE_CLASS) == 0)
{
- int flags = OMP_CLAUSE_LINEAR_NO_COPYIN (c)
- ? GOVD_LASTPRIVATE : GOVD_SHARED;
+ int flags = GOVD_FIRSTPRIVATE | GOVD_LASTPRIVATE;
if (n == NULL)
omp_add_variable (ctx->outer_context, decl,
flags | GOVD_SEEN);
n->value |= flags | GOVD_SEEN;
}
}
- else
+ else if (!is_global_var (decl))
omp_notice_variable (ctx->outer_context, decl, true);
}
}
+2014-04-30 Chris Manghane <cmang@google.com>
+
+ * go-backend.c: #include "diagnostics.h".
+ (saw_errors): New function.
+ * go-c.h (saw_errors): Declare.
+ * Make-lang.in (GO_OBJS): Remove go/gogo-tree.o.
+
+2014-04-30 Chris Manghane <cmang@google.com>
+
+ * go-lang.c (go_langhook_type_for_size): Do it here, rather than
+ calling into Go frontend.
+ (go_langhook_type_for_mode): Likewise.
+ * go-c.h (go_type_for_size, go_type_for_mode): Don't declare.
+
2014-04-30 Chris Manghane <cmang@google.com>
* go-gcc.cc: #include "langhooks.h".
go/go-linemap.o \
go/go-optimize.o \
go/go.o \
- go/gogo-tree.o \
go/gogo.o \
go/import.o \
go/import-archive.o \
#include "output.h" /* for assemble_string */
#include "target.h"
#include "common/common-target.h"
+#include "diagnostic.h"
#include "go-c.h"
/* This file holds all the cases where the Go frontend needs
information from gcc's backend. */
+/* Return whether or not GCC has reported any errors. */
+
+bool
+saw_errors (void)
+{
+ return errorcount != 0 || sorrycount != 0;
+}
+
/* Return the alignment in bytes of a struct field of type T. */
unsigned int
bool require_return_statement);
extern void go_write_globals (void);
-extern tree go_type_for_size (unsigned int bits, int unsignedp);
-extern tree go_type_for_mode (enum machine_mode, int unsignedp);
-
/* Functions defined in the GCC interface called by the Go frontend
proper. */
extern void go_preserve_from_gc (tree);
+extern bool saw_errors (void);
+
extern const char *go_localize_identifier (const char*);
extern unsigned int go_field_alignment (tree);
static tree
go_langhook_type_for_size (unsigned int bits, int unsignedp)
{
- return go_type_for_size (bits, unsignedp);
+ tree type;
+ if (unsignedp)
+ {
+ if (bits == INT_TYPE_SIZE)
+ type = unsigned_type_node;
+ else if (bits == CHAR_TYPE_SIZE)
+ type = unsigned_char_type_node;
+ else if (bits == SHORT_TYPE_SIZE)
+ type = short_unsigned_type_node;
+ else if (bits == LONG_TYPE_SIZE)
+ type = long_unsigned_type_node;
+ else if (bits == LONG_LONG_TYPE_SIZE)
+ type = long_long_unsigned_type_node;
+ else
+ type = make_unsigned_type(bits);
+ }
+ else
+ {
+ if (bits == INT_TYPE_SIZE)
+ type = integer_type_node;
+ else if (bits == CHAR_TYPE_SIZE)
+ type = signed_char_type_node;
+ else if (bits == SHORT_TYPE_SIZE)
+ type = short_integer_type_node;
+ else if (bits == LONG_TYPE_SIZE)
+ type = long_integer_type_node;
+ else if (bits == LONG_LONG_TYPE_SIZE)
+ type = long_long_integer_type_node;
+ else
+ type = make_signed_type(bits);
+ }
+ return type;
}
static tree
return NULL_TREE;
}
- type = go_type_for_mode (mode, unsignedp);
- if (type)
- return type;
+ // FIXME: This static_cast should be in machmode.h.
+ enum mode_class mc = static_cast<enum mode_class>(GET_MODE_CLASS(mode));
+ if (mc == MODE_INT)
+ return go_langhook_type_for_size(GET_MODE_BITSIZE(mode), unsignedp);
+ else if (mc == MODE_FLOAT)
+ {
+ switch (GET_MODE_BITSIZE (mode))
+ {
+ case 32:
+ return float_type_node;
+ case 64:
+ return double_type_node;
+ default:
+ // We have to check for long double in order to support
+ // i386 excess precision.
+ if (mode == TYPE_MODE(long_double_type_node))
+ return long_double_type_node;
+ }
+ }
+ else if (mc == MODE_COMPLEX_FLOAT)
+ {
+ switch (GET_MODE_BITSIZE (mode))
+ {
+ case 64:
+ return complex_float_type_node;
+ case 128:
+ return complex_double_type_node;
+ default:
+ // We have to check for long double in order to support
+ // i386 excess precision.
+ if (mode == TYPE_MODE(complex_long_double_type_node))
+ return complex_long_double_type_node;
+ }
+ }
#if HOST_BITS_PER_WIDE_INT >= 64
/* The middle-end and some backends rely on TImode being supported
Expression* ret = Expression::make_struct_composite_literal(st, vals, loc);
ret = Expression::make_heap_expression(ret, loc);
- tree ret_tree = ret->get_tree(context);
-
- Expression* nil_check = NULL;
-
// See whether the expression or any embedded pointers are nil.
+ Expression* nil_check = NULL;
Expression* expr = this->expr_;
if (this->method_->field_indexes() != NULL)
{
nil_check = Expression::make_binary(OPERATOR_OROR, nil_check, n, loc);
}
+ Bexpression* bme = tree_to_expr(ret->get_tree(context));
if (nil_check != NULL)
{
- tree nil_check_tree = nil_check->get_tree(context);
- Expression* crash_expr =
- context->gogo()->runtime_error(RUNTIME_ERROR_NIL_DEREFERENCE, loc);
- tree crash = crash_expr->get_tree(context);
- if (ret_tree == error_mark_node
- || nil_check_tree == error_mark_node
- || crash == error_mark_node)
- return error_mark_node;
-
- ret_tree = fold_build2_loc(loc.gcc_location(), COMPOUND_EXPR,
- TREE_TYPE(ret_tree),
- build3_loc(loc.gcc_location(), COND_EXPR,
- void_type_node, nil_check_tree,
- crash, NULL_TREE),
- ret_tree);
+ Gogo* gogo = context->gogo();
+ Expression* crash =
+ gogo->runtime_error(RUNTIME_ERROR_NIL_DEREFERENCE, loc);
+ Bexpression* bcrash = tree_to_expr(crash->get_tree(context));
+ Btype* btype = ret->type()->get_backend(gogo);
+ Bexpression* bcheck = tree_to_expr(nil_check->get_tree(context));
+ bme = gogo->backend()->conditional_expression(btype, bcheck, bcrash,
+ bme, loc);
}
-
- return ret_tree;
+ return expr_to_tree(bme);
}
// Dump ast representation of a bound method expression.
tree
Heap_expression::do_get_tree(Translate_context* context)
{
- tree expr_tree = this->expr_->get_tree(context);
- if (expr_tree == error_mark_node || TREE_TYPE(expr_tree) == error_mark_node)
+ if (this->expr_->is_error_expression() || this->expr_->type()->is_error())
return error_mark_node;
- Expression* alloc =
- Expression::make_allocation(this->expr_->type(), this->location());
-
+ Location loc = this->location();
Gogo* gogo = context->gogo();
- Btype* btype = this->expr_->type()->get_backend(gogo);
- size_t expr_size = gogo->backend()->type_size(btype);
- tree space = alloc->get_tree(context);
- if (expr_size == 0)
- return space;
-
- space = save_expr(space);
- tree ref = build_fold_indirect_ref_loc(this->location().gcc_location(),
- space);
- TREE_THIS_NOTRAP(ref) = 1;
- tree ret = build2(COMPOUND_EXPR,
- type_to_tree(this->type()->get_backend(gogo)),
- build2(MODIFY_EXPR, void_type_node, ref, expr_tree),
- space);
- SET_EXPR_LOCATION(ret, this->location().gcc_location());
- return ret;
+ Btype* btype = this->type()->get_backend(gogo);
+ Expression* alloc = Expression::make_allocation(this->expr_->type(), loc);
+ Bexpression* space = tree_to_expr(alloc->get_tree(context));
+
+ Bstatement* decl;
+ Named_object* fn = context->function();
+ go_assert(fn != NULL);
+ Bfunction* fndecl = fn->func_value()->get_or_make_decl(gogo, fn);
+ Bvariable* space_temp =
+ gogo->backend()->temporary_variable(fndecl, context->bblock(), btype,
+ space, true, loc, &decl);
+ space = gogo->backend()->var_expression(space_temp, loc);
+ Bexpression* ref = gogo->backend()->indirect_expression(space, true, loc);
+
+ Bexpression* bexpr = tree_to_expr(this->expr_->get_tree(context));
+ Bstatement* assn = gogo->backend()->assignment_statement(ref, bexpr, loc);
+ decl = gogo->backend()->compound_statement(decl, assn);
+ space = gogo->backend()->var_expression(space_temp, loc);
+ Bexpression* ret = gogo->backend()->compound_expression(decl, space, loc);
+ return expr_to_tree(ret);
}
// Dump ast representation for a heap expression.
+++ /dev/null
-// gogo-tree.cc -- convert Go frontend Gogo IR to gcc trees.
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "go-system.h"
-
-#include "toplev.h"
-#include "tree.h"
-#include "stringpool.h"
-#include "stor-layout.h"
-#include "varasm.h"
-#include "gimple-expr.h"
-#include "gimplify.h"
-#include "tree-iterator.h"
-#include "cgraph.h"
-#include "langhooks.h"
-#include "convert.h"
-#include "output.h"
-#include "diagnostic.h"
-#include "go-c.h"
-
-#include "types.h"
-#include "expressions.h"
-#include "statements.h"
-#include "runtime.h"
-#include "backend.h"
-#include "gogo.h"
-
-// Whether we have seen any errors.
-
-bool
-saw_errors()
-{
- return errorcount != 0 || sorrycount != 0;
-}
-
-// Return the integer type to use for a size.
-
-GO_EXTERN_C
-tree
-go_type_for_size(unsigned int bits, int unsignedp)
-{
- const char* name;
- switch (bits)
- {
- case 8:
- name = unsignedp ? "uint8" : "int8";
- break;
- case 16:
- name = unsignedp ? "uint16" : "int16";
- break;
- case 32:
- name = unsignedp ? "uint32" : "int32";
- break;
- case 64:
- name = unsignedp ? "uint64" : "int64";
- break;
- default:
- if (bits == POINTER_SIZE && unsignedp)
- name = "uintptr";
- else
- return NULL_TREE;
- }
- Type* type = Type::lookup_integer_type(name);
- return type_to_tree(type->get_backend(go_get_gogo()));
-}
-
-// Return the type to use for a mode.
-
-GO_EXTERN_C
-tree
-go_type_for_mode(enum machine_mode mode, int unsignedp)
-{
- // FIXME: This static_cast should be in machmode.h.
- enum mode_class mc = static_cast<enum mode_class>(GET_MODE_CLASS(mode));
- if (mc == MODE_INT)
- return go_type_for_size(GET_MODE_BITSIZE(mode), unsignedp);
- else if (mc == MODE_FLOAT)
- {
- Type* type;
- switch (GET_MODE_BITSIZE (mode))
- {
- case 32:
- type = Type::lookup_float_type("float32");
- break;
- case 64:
- type = Type::lookup_float_type("float64");
- break;
- default:
- // We have to check for long double in order to support
- // i386 excess precision.
- if (mode == TYPE_MODE(long_double_type_node))
- return long_double_type_node;
- return NULL_TREE;
- }
- return type_to_tree(type->get_backend(go_get_gogo()));
- }
- else if (mc == MODE_COMPLEX_FLOAT)
- {
- Type *type;
- switch (GET_MODE_BITSIZE (mode))
- {
- case 64:
- type = Type::lookup_complex_type("complex64");
- break;
- case 128:
- type = Type::lookup_complex_type("complex128");
- break;
- default:
- // We have to check for long double in order to support
- // i386 excess precision.
- if (mode == TYPE_MODE(complex_long_double_type_node))
- return complex_long_double_type_node;
- return NULL_TREE;
- }
- return type_to_tree(type->get_backend(go_get_gogo()));
- }
- else
- return NULL_TREE;
-}
Bstatement* var_init_stmt = NULL;
if (!var->has_pre_init())
{
- Bexpression* var_binit = var->get_init(this, NULL);
-
// If the backend representation of the variable initializer is
// constant, we can just set the initial value using
// global_var_set_init instead of during the init() function.
init_cast->is_immutable() && !var_type->has_pointer();
}
+ // Non-constant variable initializations might need to create
+ // temporary variables, which will need the initialization
+ // function as context.
+ if (!is_constant_initializer && init_fndecl == NULL)
+ init_fndecl = this->initialization_function_decl();
+ Bexpression* var_binit = var->get_init(this, init_fndecl);
+
if (var_binit == NULL)
;
else if (is_constant_initializer)
else
{
gcc_checking_assert (prec < HOST_BITS_PER_WIDE_INT);
- return src & (((HOST_WIDE_INT) 1 << prec) - 1);
+ return src & (((unsigned HOST_WIDE_INT) 1 << prec) - 1);
}
}
}
return j == nregs;
}
-#ifndef HONOR_REG_ALLOC_ORDER
/* Return number of registers needed to be saved and restored at
function prologue/epilogue if we allocate HARD_REGNO to hold value
nregs++;
return nregs;
}
-#endif
/* Choose a hard register for allocno A. If RETRY_P is TRUE, it means
that the function called from function
enum reg_class aclass;
enum machine_mode mode;
static int costs[FIRST_PSEUDO_REGISTER], full_costs[FIRST_PSEUDO_REGISTER];
-#ifndef HONOR_REG_ALLOC_ORDER
int saved_nregs;
enum reg_class rclass;
int add_cost;
-#endif
#ifdef STACK_REGS
bool no_stack_reg_p;
#endif
continue;
cost = costs[i];
full_cost = full_costs[i];
-#ifndef HONOR_REG_ALLOC_ORDER
- if ((saved_nregs = calculate_saved_nregs (hard_regno, mode)) != 0)
- /* We need to save/restore the hard register in
- epilogue/prologue. Therefore we increase the cost. */
+ if (!HONOR_REG_ALLOC_ORDER)
{
- rclass = REGNO_REG_CLASS (hard_regno);
- add_cost = ((ira_memory_move_cost[mode][rclass][0]
- + ira_memory_move_cost[mode][rclass][1])
- * saved_nregs / hard_regno_nregs[hard_regno][mode] - 1);
- cost += add_cost;
- full_cost += add_cost;
+ if ((saved_nregs = calculate_saved_nregs (hard_regno, mode)) != 0)
+ /* We need to save/restore the hard register in
+ epilogue/prologue. Therefore we increase the cost. */
+ {
+ rclass = REGNO_REG_CLASS (hard_regno);
+ add_cost = ((ira_memory_move_cost[mode][rclass][0]
+ + ira_memory_move_cost[mode][rclass][1])
+ * saved_nregs / hard_regno_nregs[hard_regno][mode] - 1);
+ cost += add_cost;
+ full_cost += add_cost;
+ }
}
-#endif
if (min_cost > cost)
min_cost = cost;
if (min_full_cost > full_cost)
return get_reg_class (regno) == NO_REGS;
}
+/* Return 1 if ADDR is a valid memory address for mode MODE in address
+ space AS, and check that each pseudo has the proper kind of hard
+ reg. */
+static int
+valid_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
+ rtx addr, addr_space_t as)
+{
+#ifdef GO_IF_LEGITIMATE_ADDRESS
+ lra_assert (ADDR_SPACE_GENERIC_P (as));
+ GO_IF_LEGITIMATE_ADDRESS (mode, addr, win);
+ return 0;
+
+ win:
+ return 1;
+#else
+ return targetm.addr_space.legitimate_address_p (mode, addr, 0, as);
+#endif
+}
+
+/* Return whether address AD is valid. If CONSTRAINT is null,
+ check for general addresses, otherwise check the extra constraint
+ CONSTRAINT. */
+static bool
+valid_address_p (struct address_info *ad, const char *constraint = 0)
+{
+ /* Some ports do not check displacements for eliminable registers,
+ so we replace them temporarily with the elimination target. */
+ rtx saved_base_reg = NULL_RTX;
+ rtx saved_index_reg = NULL_RTX;
+ rtx *base_term = strip_subreg (ad->base_term);
+ rtx *index_term = strip_subreg (ad->index_term);
+ if (base_term != NULL)
+ {
+ saved_base_reg = *base_term;
+ lra_eliminate_reg_if_possible (base_term);
+ if (ad->base_term2 != NULL)
+ *ad->base_term2 = *ad->base_term;
+ }
+ if (index_term != NULL)
+ {
+ saved_index_reg = *index_term;
+ lra_eliminate_reg_if_possible (index_term);
+ }
+ bool ok_p = (constraint
+#ifdef EXTRA_CONSTRAINT_STR
+ ? EXTRA_CONSTRAINT_STR (*ad->outer, constraint[0], constraint)
+#else
+ ? false
+#endif
+ : valid_address_p (ad->mode, *ad->outer, ad->as));
+ if (saved_base_reg != NULL_RTX)
+ {
+ *base_term = saved_base_reg;
+ if (ad->base_term2 != NULL)
+ *ad->base_term2 = *ad->base_term;
+ }
+ if (saved_index_reg != NULL_RTX)
+ *index_term = saved_index_reg;
+ return ok_p;
+}
+
+#ifdef EXTRA_CONSTRAINT_STR
+/* Return true if, after elimination, OP satisfies extra memory constraint
+ CONSTRAINT. */
+static bool
+satisfies_memory_constraint_p (rtx op, const char *constraint)
+{
+ struct address_info ad;
+
+ if (!MEM_P (op))
+ return false;
+
+ decompose_mem_address (&ad, op);
+ return valid_address_p (&ad, constraint);
+}
+
+/* Return true if, after elimination, OP satisfies extra address constraint
+ CONSTRAINT. */
+static bool
+satisfies_address_constraint_p (rtx op, const char *constraint)
+{
+ struct address_info ad;
+
+ decompose_lea_address (&ad, &op);
+ return valid_address_p (&ad, constraint);
+}
+#endif
+
/* Initiate equivalences for LRA. As we keep original equivalences
before any elimination, we need to make copies otherwise any change
in insns might change the equivalences. */
#ifdef EXTRA_CONSTRAINT_STR
if (EXTRA_MEMORY_CONSTRAINT (c, p))
{
- if (EXTRA_CONSTRAINT_STR (op, c, p))
+ if (satisfies_memory_constraint_p (op, p))
win = true;
else if (spilled_pseudo_p (op))
win = true;
}
if (EXTRA_ADDRESS_CONSTRAINT (c, p))
{
- if (EXTRA_CONSTRAINT_STR (op, c, p))
+ if (satisfies_address_constraint_p (op, p))
win = true;
/* If we didn't already win, we can reload
return ok_p;
}
-/* Return 1 if ADDR is a valid memory address for mode MODE in address
- space AS, and check that each pseudo has the proper kind of hard
- reg. */
-static int
-valid_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
- rtx addr, addr_space_t as)
-{
-#ifdef GO_IF_LEGITIMATE_ADDRESS
- lra_assert (ADDR_SPACE_GENERIC_P (as));
- GO_IF_LEGITIMATE_ADDRESS (mode, addr, win);
- return 0;
-
- win:
- return 1;
-#else
- return targetm.addr_space.legitimate_address_p (mode, addr, 0, as);
-#endif
-}
-
-/* Return whether address AD is valid. */
-
-static bool
-valid_address_p (struct address_info *ad)
-{
- /* Some ports do not check displacements for eliminable registers,
- so we replace them temporarily with the elimination target. */
- rtx saved_base_reg = NULL_RTX;
- rtx saved_index_reg = NULL_RTX;
- rtx *base_term = strip_subreg (ad->base_term);
- rtx *index_term = strip_subreg (ad->index_term);
- if (base_term != NULL)
- {
- saved_base_reg = *base_term;
- lra_eliminate_reg_if_possible (base_term);
- if (ad->base_term2 != NULL)
- *ad->base_term2 = *ad->base_term;
- }
- if (index_term != NULL)
- {
- saved_index_reg = *index_term;
- lra_eliminate_reg_if_possible (index_term);
- }
- bool ok_p = valid_address_p (ad->mode, *ad->outer, ad->as);
- if (saved_base_reg != NULL_RTX)
- {
- *base_term = saved_base_reg;
- if (ad->base_term2 != NULL)
- *ad->base_term2 = *ad->base_term;
- }
- if (saved_index_reg != NULL_RTX)
- *index_term = saved_index_reg;
- return ok_p;
-}
-
/* Make reload base reg + disp from address AD. Return the new pseudo. */
static rtx
base_plus_disp_to_reg (struct address_info *ad)
EXTRA_CONSTRAINT_STR for the validation. */
if (constraint[0] != 'p'
&& EXTRA_ADDRESS_CONSTRAINT (constraint[0], constraint)
- && EXTRA_CONSTRAINT_STR (op, constraint[0], constraint))
+ && valid_address_p (&ad, constraint))
return change_p;
#endif
break;
#ifdef EXTRA_CONSTRAINT_STR
if (EXTRA_MEMORY_CONSTRAINT (c, constraint)
- && EXTRA_CONSTRAINT_STR (tem, c, constraint))
+ && satisfies_memory_constraint_p (tem, constraint))
break;
#endif
}
{
stmt = gimple_build_assign (endvar, iend);
gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
+ if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
+ stmt = gimple_build_assign (fd->loop.v, iend);
+ else
+ stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, iend,
+ NULL_TREE);
+ gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
}
if (fd->collapse > 1)
expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
{
stmt = gimple_build_assign (endvar, e);
gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
+ if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
+ stmt = gimple_build_assign (fd->loop.v, e);
+ else
+ stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, e,
+ NULL_TREE);
+ gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
}
if (fd->collapse > 1)
expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
{
stmt = gimple_build_assign (endvar, e);
gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
+ if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
+ stmt = gimple_build_assign (fd->loop.v, e);
+ else
+ stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, e,
+ NULL_TREE);
+ gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
}
if (fd->collapse > 1)
expand_omp_for_init_vars (fd, &si, counts, inner_stmt, startvar);
/* IPA passes leave stmts to be fixed up, so make sure to
not verify SSA operands whose verifier will choke on that. */
verify_ssa (true, !from_ipa_pass);
- }
- if (flags & TODO_verify_flow)
- verify_flow_info ();
- if (flags & TODO_verify_il)
- {
+ /* IPA passes leave basic-blocks unsplit, so make sure to
+ not trip on that. */
+ if ((cfun->curr_properties & PROP_cfg)
+ && !from_ipa_pass)
+ verify_flow_info ();
if (current_loops
&& loops_state_satisfies_p (LOOP_CLOSED_SSA))
verify_loop_closed_ssa (false);
+2014-05-01 Jeff Law <law@redhat.com>
+
+ * Revert:
+ 2014-04-24 Jincheng Miao <jincheng.miao@gmail.com>
+
+ * zh_CN.po: Fix typo for -mfentry.
+
+2014-05-01 Joseph Myers <joseph@codesourcery.com>
+
+ * sv.po: Update.
+
2014-04-24 Jincheng Miao <jincheng.miao@gmail.com>
* zh_CN.po: Fix typo for -mfentry.
"Project-Id-Version: gcc 4.9-b20140202\n"
"Report-Msgid-Bugs-To: http://gcc.gnu.org/bugs.html\n"
"POT-Creation-Date: 2014-02-02 17:35+0000\n"
-"PO-Revision-Date: 2014-03-30 20:23+0200\n"
+"PO-Revision-Date: 2014-04-11 20:56+0200\n"
"Last-Translator: Göran Uddeborg <goeran@uddeborg.se>\n"
"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
"Language: sv\n"
#: cif-code.def:125
msgid "callee refers to comdat-local symbols"
-msgstr "den anropade referarar till comdat-lokala symboler"
+msgstr "den anropade refererar till comdat-lokala symboler"
#. The remainder are real diagnostic types.
#: diagnostic.def:33
#: c-family/c.opt:653
msgid "Warn about __TIME__, __DATE__ and __TIMESTAMP__ usage"
-msgstr "Warn för använding av __TIME__, __DATE__ och __TIMESTAMP__"
+msgstr "Varna för användning av __TIME__, __DATE__ och __TIMESTAMP__"
#: c-family/c.opt:657
msgid "Warn if a property for an Objective-C object has no assign semantics specified"
#: common.opt:811
msgid "Aggressively optimize loops using language constraints"
-msgstr "Optimera aggresivt slingor med användning av språkbegränsningar"
+msgstr "Optimera aggressivt slingor med användning av språkbegränsningar"
#: common.opt:815
msgid "Align the start of functions"
#: common.opt:2332
msgid "Enables the dynamic vectorizer cost model. Preserved for backward compatibility."
-msgstr "Aktivera den dynamiska kostnadsmodellen för vekoriseraren. Bevarad för bakåtkompatibilitet."
+msgstr "Aktivera den dynamiska kostnadsmodellen för vektoriseraren. Bevarad för bakåtkompatibilitet."
#: common.opt:2336
msgid "Enables the unlimited vectorizer cost model. Preserved for backward compatibility."
#: c/c-array-notation.c:721 cp/cp-array-notation.c:610
#, gcc-internal-format
msgid "rank mismatch between %qE and %qE"
-msgstr "ordingen stämmer inte mellan %qE och %qE"
+msgstr "ordningen stämmer inte mellan %qE och %qE"
#. Here the original expression is printed as a "heads-up"
#. to the programmer. This is because since there is no
msgid "too much stack space to dispose of: %d"
msgstr "för mycket stackutrymme att göra av med: %d"
-# Förmodligen en felstavning i orginalet, men tills jag vet säkert
+# Förmodligen en felstavning i originalet, men tills jag vet säkert
# behåller jag den
#: config/v850/v850.c:2788
#, gcc-internal-format, gfc-internal-format
#: c/c-parser.c:6884
#, gcc-internal-format
msgid "%<_Generic%> selector of type %qT is not compatible with any association"
-msgstr "%<_Generic%>-väljare av typ %qT är inte kompatiblem med någon association"
+msgstr "%<_Generic%>-väljare av typ %qT är inte kompatibel med någon association"
#: c/c-parser.c:7039 c/c-parser.c:7519 c/c-parser.c:7538
#, gcc-internal-format
#: c/c-parser.c:7505 cp/parser.c:5807
#, gcc-internal-format
msgid "consecutive %<_Cilk_spawn%> keywords are not permitted"
-msgstr "konsektiva %<_Cilk_spawn%>-nyckelord är inte tillåtet"
+msgstr "konsekutiva %<_Cilk_spawn%>-nyckelord är inte tillåtet"
#: c/c-parser.c:7573
#, gcc-internal-format
#: cp/cp-array-notation.c:849 cp/cp-array-notation.c:855
#, gcc-internal-format
msgid "rank mismatch with controlling expression of parent if-statement"
-msgstr "ordingen stämmer inte med det styrande uttrycket i förälder-if-satsen"
+msgstr "ordningen stämmer inte med det styrande uttrycket i förälder-if-satsen"
#: cp/cp-array-notation.c:1250
#, gcc-internal-format
#: cp/cp-array-notation.c:1422
#, gcc-internal-format
msgid "array notation cannot be used with function type"
-msgstr "vektornotation kan inte användas användas med en funktionstyp"
+msgstr "vektornotation kan inte användas med en funktionstyp"
#: cp/cp-array-notation.c:1432
#, gcc-internal-format
#: cp/cp-array-notation.c:1438
#, gcc-internal-format
msgid "rank of an array notation triplet%'s length is not zero"
-msgstr "ordingen på en vektornotations trippels längd är inte noll"
+msgstr "ordningen på en vektornotations trippels längd är inte noll"
#: cp/cp-array-notation.c:1443
#, gcc-internal-format
#: cp/cvt.c:1659
#, gcc-internal-format
msgid "ambiguous default type conversion from %qT"
-msgstr "tvetydig standartypkonvertering från %qT"
+msgstr "tvetydig standardtypkonvertering från %qT"
#: cp/cvt.c:1661
#, gcc-internal-format
#: cp/decl.c:14531 cp/decl2.c:4673
#, gcc-internal-format
msgid "use of %qD before deduction of %<auto%>"
-msgstr "använding av %qD före härledning av %<auto%>"
+msgstr "användning av %qD före härledning av %<auto%>"
#: cp/decl2.c:322
#, gcc-internal-format
#: cp/parser.c:14516
#, gcc-internal-format
msgid "use of %<auto%> in parameter declaration only available with -std=c++1y or -std=gnu++1y"
-msgstr "använding av %<auto%> i parameterdeklarationer är endast tillgängligt med -std=c++1y eller -std=gnu++1y"
+msgstr "användning av %<auto%> i parameterdeklarationer är endast tillgängligt med -std=c++1y eller -std=gnu++1y"
#: cp/parser.c:14521
#, gcc-internal-format
#: cp/pt.c:4861
#, gcc-internal-format
msgid "template arguments to %qD do not match original template %qD"
-msgstr "mallargument till %qD stämmer inte med orginalmallen %qD"
+msgstr "mallargument till %qD stämmer inte med originalmallen %qD"
#: cp/pt.c:4865
#, gcc-internal-format
#: cp/semantics.c:3800
#, gcc-internal-format
msgid "second operand of %<offsetof%> is neither a single identifier nor a sequence of member accesses and array references"
-msgstr "andra operanden till %<offsetof%> är varken en ensam idientifierare eller en sekvens av medlemsåtkomster och vektorreferenser"
+msgstr "andra operanden till %<offsetof%> är varken en ensam identifierare eller en sekvens av medlemsåtkomster och vektorreferenser"
#: cp/semantics.c:3808
#, gcc-internal-format
#: fortran/resolve.c:13229
#, gcc-internal-format, gfc-internal-format
msgid "Variable '%s' at %L with coarray component shall be a nonpointer, nonallocatable scalar, which is not a coarray"
-msgstr "Variabeln ”%s” vid %L med co-vektorkomponent skall vara en skalär som inte är en pekare eller allokerbar och inte en co-vaktor"
+msgstr "Variabeln ”%s” vid %L med co-vektorkomponent skall vara en skalär som inte är en pekare eller allokerbar och inte en co-vektor"
#: fortran/resolve.c:13244
#, gcc-internal-format, gfc-internal-format
#: lto/lto-symtab.c:404
#, gcc-internal-format
msgid "type of %qD does not match original declaration"
-msgstr "typen på %qD stämmer inte med orginaldeklarationen"
+msgstr "typen på %qD stämmer inte med originaldeklarationen"
#: lto/lto-symtab.c:412
#, gcc-internal-format
msgid "alignment of %qD is bigger than original declaration"
-msgstr "justering av %qD är större än orginaldeklarationen"
+msgstr "justering av %qD är större än originaldeklarationen"
#: lto/lto-symtab.c:418 lto/lto-symtab.c:517
#, gcc-internal-format
#: config/i386/i386.c:4108
#, gcc-internal-format
msgid "-mfentry isn%'t supported for 32-bit in combination with -fpic"
-msgstr "-mfentry 在 32 位下不能和 -fpic 同时使用"
+msgstr "-mfentry 在 32 位下不能和 -pic 同时使用"
#: config/i386/i386.c:4115
#, gcc-internal-format
bool, (void),
default_profile_before_prologue)
+/* Return true if a leaf function should stay leaf even with profiling
+ enabled. */
+DEFHOOK
+(keep_leaf_when_profiled,
+ "This target hook returns true if the target wants the leaf flag for\
+ the current function to stay true even if it calls mcount. This might\
+ make sense for targets using the leaf flag only to determine whether a\
+ stack frame needs to be generated or not and for which the call to\
+ mcount is generated before the function prologue.",
+ bool, (void),
+ default_keep_leaf_when_profiled)
+
/* Modify and return the identifier of a DECL's external name,
originally identified by ID, as required by the target,
(eg, append @nn to windows32 stdcall function names).
return reg_raw_mode[regno];
}
+/* Return true if a leaf function should stay leaf even with profiling
+ enabled. */
+
+bool
+default_keep_leaf_when_profiled ()
+{
+ return false;
+}
+
/* Return true if the state of option OPTION should be stored in PCH files
and checked by default_pch_valid_p. Store the option's current state
in STATE if so. */
extern section * default_function_section(tree decl, enum node_frequency freq,
bool startup, bool exit);
extern enum machine_mode default_get_reg_raw_mode (int);
+extern bool default_keep_leaf_when_profiled ();
extern void *default_get_pch_validity (size_t *);
extern const char *default_pch_valid_p (const void *, size_t);
+2014-05-05 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/61010
+ * gcc.dg/torture/pr61010.c: New testcase.
+
+2014-05-05 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ * gcc.target/s390/leaf-profile.c: New testcase.
+
+2014-05-05 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ * gcc.dg/hoist-register-pressure-1.c: Replace int with long.
+ Disable asm scan for s390.
+ * gcc.dg/hoist-register-pressure-2.c: Likewise.
+ * gcc.dg/hoist-register-pressure-3.c: Likewise.
+
+2014-05-05 Bin Cheng <bin.cheng@arm.com>
+
+ PR tree-optimization/60363
+ * gcc.dg/tree-ssa/ssa-dom-thread-4.c: Revert XFAIL test.
+
+2014-05-04 Peter Bergner <bergner@vnet.ibm.com>
+
+ * gcc.target/powerpc/pack02.c (dg-options): Add -mhard-float.
+ (dg-require-effective-target): Change target to powerpc_fprs.
+ * gcc.target/powerpc/pack03.c (dg-options): Add -mhard-dfp.
+ (dg-require-effective-target): Change target to dfprt.
+
+2014-05-03 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58582
+ * g++.dg/cpp0x/deleted4.C: New.
+ * g++.dg/cpp0x/deleted5.C: Likewise.
+ * g++.dg/cpp0x/deleted6.C: Likewise.
+
+2014-05-03 Dominique d'Humieres <dominiq@lps.ens.fr>
+
+ PR fortran/61025
+ * gfortran.dg/coarray_lib_this_image_1.f90: Adjust the dg-final
+ regexps for -m32.
+ * gfortran.dg/coarray_lib_this_image_2.f90: Likewise.
+ * gfortran.dg/coarray_poly_6.f90: Likewise.
+ * gfortran.dg/coarray_poly_7.f90: Likewise.
+ * gfortran.dg/coarray_poly_8.f90: Likewise.
+
+2014-05-02 Marek Polacek <polacek@redhat.com>
+
+ PR c/25801
+ * gcc.dg/pr25801.c: New test.
+
+2014-05-02 Marek Polacek <polacek@redhat.com>
+
+ PR c/60784
+ * gcc.dg/pr60784.c: New test.
+
+2014-05-01 Marek Polacek <polacek@redhat.com>
+
+ PR c/60915
+ * gcc.dg/pr60915.c: New test.
+
+2014-05-01 Marek Polacek <polacek@redhat.com>
+
+ PR c/60257
+ * gcc.dg/pr60257.c: New test.
+
+2014-05-01 Marek Polacek <polacek@redhat.com>
+
+ PR c/43395
+ * c-c++-common/pr43395.c: New test.
+
+2014-05-01 Yuri Rumyantsev <ysrumyan@gmail.com>
+
+ * gcc.dg/cond-reduc-1.c: New test.
+ * gcc.dg/cond-reduc-2.c: Likewise.
+
+2014-05-01 Marek Polacek <polacek@redhat.com>
+
+ PR c/29467
+ * gcc.dg/pr29467.c: New test.
+ * gcc.dg/declspec-13.c: Renumber some dg-warnings. Add dg-warnings
+ about boolean types.
+ * gfortran.dg/bind_c_usage_24_c.c: Include <stdbool.h>. Change _Bool
+ to bool.
+ * gfortran.dg/c_f_pointer_logical_driver.c: Change _Bool to bool.
+
+2014-05-01 Marek Polacek <polacek@redhat.com>
+
+ PR c/43245
+ * gcc.dg/pr43245.c: New test.
+
+2014-05-01 Marek Polacek <polacek@redhat.com>
+
+ PR c/56989
+ * gcc.dg/pr56989.c: New test.
+
+2014-04-30 Ian Lance Taylor <iant@google.com>
+
+ * go.test/go-test.exp (go-gc-tests): For rundir, pass extra files
+ in go_compile_args rather than in argument to go-torture-execute.
+
+2014-04-30 Soundararajan Dhakshinamoorthy <sounderarajan.d@atmel.com>
+
+ * gcc.c-torture/execute/pr58419.c: Use dummy no-inline function
+ instead of getpid.
+
+2014-04-30 Tobias Burnus <burnus@net-b.de>
+
+ * gfortran.dg/coarray_poly_6.f90
+ * gfortran.dg/coarray_poly_7.f90
+ * gfortran.dg/coarray_poly_8.f90
+
+2014-04-30 Tobias Burnus <burnus@net-b.de>
+
+ * gfortran.dg/coarray_lib_this_image_2.f90: Update dump.
+ * gfortran.dg/coarray_lib_token_4.f90: Ditto.
+ * gfortran.dg/coarray/codimension.f90: New.
+
+2014-04-30 Tobias Burnus <burnus@net-b.de>
+
+ * gfortran.dg/coarray_lib_this_image_1.f90: New.
+ * gfortran.dg/coarray_lib_this_image_2.f90: New.
+
+2014-04-30 Tobias Burnus <burnus@net-b.de>
+
+ * gfortran.dg/coarray_poly_4.f90: New.
+ * gfortran.dg/coarray_poly_5.f90: New.
+
+2014-04-30 Alan Lawrence <alan.lawrence@arm.com>
+
+ * gcc.target/arm/simd/vuzpqf32_1.c: New file.
+ * gcc.target/arm/simd/vuzpqp16_1.c: New file.
+ * gcc.target/arm/simd/vuzpqp8_1.c: New file.
+ * gcc.target/arm/simd/vuzpqs16_1.c: New file.
+ * gcc.target/arm/simd/vuzpqs32_1.c: New file.
+ * gcc.target/arm/simd/vuzpqs8_1.c: New file.
+ * gcc.target/arm/simd/vuzpqu16_1.c: New file.
+ * gcc.target/arm/simd/vuzpqu32_1.c: New file.
+ * gcc.target/arm/simd/vuzpqu8_1.c: New file.
+ * gcc.target/arm/simd/vuzpf32_1.c: New file.
+ * gcc.target/arm/simd/vuzpp16_1.c: New file.
+ * gcc.target/arm/simd/vuzpp8_1.c: New file.
+ * gcc.target/arm/simd/vuzps16_1.c: New file.
+ * gcc.target/arm/simd/vuzps32_1.c: New file.
+ * gcc.target/arm/simd/vuzps8_1.c: New file.
+ * gcc.target/arm/simd/vuzpu16_1.c: New file.
+ * gcc.target/arm/simd/vuzpu32_1.c: New file.
+ * gcc.target/arm/simd/vuzpu8_1.c: New file.
+
2014-04-30 Alan Lawrence <alan.lawrence@arm.com>
* gcc.target/aarch64/vuzps32_1.c: Expect zip1/2 insn rather than uzp1/2.
--- /dev/null
+/* PR c/43395 */
+/* { dg-do compile } */
+
+void *
+foo (void)
+{
+lab:
+ return &&lab;
+/* { dg-warning "function returns address of label" "" { target c } 8 } */
+/* { dg-warning "address of label" "" { target c++ } 7 } */
+}
+
+void *
+bar (void)
+{
+ __label__ lab;
+lab:
+ return &&lab;
+/* { dg-warning "function returns address of label" "" { target c } 18 } */
+/* { dg-warning "address of label" "" { target c++ } 17 } */
+}
+
+void *
+baz (void)
+{
+ int i;
+ return &i;
+/* { dg-warning "function returns address of local variable" "" { target c } 27 } */
+/* { dg-warning "address of local variable" "" { target c++ } 26 } */
+}
--- /dev/null
+// PR c++/58582
+// { dg-do compile { target c++11 } }
+
+struct A
+{
+ template<int> void foo() = delete;
+};
+
+template<int> void A::foo() { int i; } // { dg-error "redefinition" }
+
+template void A::foo<0>();
--- /dev/null
+// PR c++/58582
+// { dg-do compile { target c++11 } }
+
+struct A
+{
+ template<int> void foo() = delete;
+};
+
+template<int> void A::foo() {} // { dg-error "redefinition" }
+
+template void A::foo<0>();
--- /dev/null
+// PR c++/58582
+// { dg-do compile { target c++11 } }
+
+struct A
+{
+ template<int> void foo() = delete;
+};
+
+template void A::foo<0>();
--- /dev/null
+// PR c++/60992
+// { dg-do compile { target c++11 } }
+
+struct ScopeGuardGenerator { };
+
+struct FF
+{
+ template < class F, class ... Ts >
+ void
+ operator () (F & ...)
+ {
+ const int n = sizeof ... (Ts) + 1;
+ void *mutexes[n];
+ auto _on_scope_exit_var_0 =
+ ScopeGuardGenerator () + [&mutexes] { };
+ }
+};
+
+template < class F >
+int operator+ (ScopeGuardGenerator, F) { return 1; }
+
+struct D
+{
+ template < class T0, class T1, class T2, class ... T >
+ void
+ operator () (T0, T1, const T2 & t2, T & ... t)
+ {
+ base (t2, t ...);
+ }
+ FF base;
+};
+
+D run_with_locks;
+
+void Fn ()
+{
+ run_with_locks ([] { }, 0, 0);
+}
-int printf(const char *, ...);
+__attribute__((__noinline__))
+void
+dummy ()
+{
+ asm volatile("");
+}
int a, g, i, k, *p;
signed char b;
*l = a;
g = foo (*m = k && *d, 1 > i) || bar ();
}
- getpid();
+ dummy();
return 0;
}
short long x4; /* { dg-error "both 'long' and 'short' in declaration specifiers" } */
void long x5; /* { dg-error "both 'long' and 'void' in declaration specifiers" } */
_Bool long x6; /* { dg-error "both 'long' and '_Bool' in declaration specifiers" } */
+/* { dg-warning "ISO C90 does not support boolean types" "C90" { target *-*-* } 38 } */
char long x7; /* { dg-error "both 'long' and 'char' in declaration specifiers" } */
float long x8; /* { dg-error "both 'long' and 'float' in declaration specifiers" } */
long short x9; /* { dg-error "both 'long' and 'short' in declaration specifiers" } */
void short x10; /* { dg-error "both 'short' and 'void' in declaration specifiers" } */
_Bool short x11; /* { dg-error "both 'short' and '_Bool' in declaration specifiers" } */
+/* { dg-warning "ISO C90 does not support boolean types" "C90" { target *-*-* } 44 } */
char short x12; /* { dg-error "both 'short' and 'char' in declaration specifiers" } */
float short x13; /* { dg-error "both 'short' and 'float' in declaration specifiers" } */
double short x14; /* { dg-error "both 'short' and 'double' in declaration specifiers" } */
unsigned signed x15; /* { dg-error "both 'signed' and 'unsigned' in declaration specifiers" } */
void signed x16; /* { dg-error "both 'signed' and 'void' in declaration specifiers" } */
_Bool signed x17; /* { dg-error "both 'signed' and '_Bool' in declaration specifiers" } */
+/* { dg-warning "ISO C90 does not support boolean types" "C90" { target *-*-* } 51 } */
float signed x18; /* { dg-error "both 'signed' and 'float' in declaration specifiers" } */
double signed x19; /* { dg-error "both 'signed' and 'double' in declaration specifiers" } */
signed unsigned x20; /* { dg-error "both 'signed' and 'unsigned' in declaration specifiers" } */
void unsigned x21; /* { dg-error "both 'unsigned' and 'void' in declaration specifiers" } */
_Bool unsigned x22; /* { dg-error "both 'unsigned' and '_Bool' in declaration specifiers" } */
+/* { dg-warning "ISO C90 does not support boolean types" "C90" { target *-*-* } 57 } */
float unsigned x23; /* { dg-error "both 'unsigned' and 'float' in declaration specifiers" } */
double unsigned x24; /* { dg-error "both 'unsigned' and 'double' in declaration specifiers" } */
void _Complex x25; /* { dg-error "both 'complex' and 'void' in declaration specifiers" } */
-/* { dg-warning "ISO C90 does not support complex types" "C90" { target *-*-* } 57 } */
+/* { dg-warning "ISO C90 does not support complex types" "C90" { target *-*-* } 61 } */
_Bool _Complex x26; /* { dg-error "both 'complex' and '_Bool' in declaration specifiers" } */
-/* { dg-warning "ISO C90 does not support complex types" "C90" { target *-*-* } 59 } */
+/* { dg-warning "ISO C90 does not support complex types" "C90" { target *-*-* } 63 } */
+/* { dg-warning "ISO C90 does not support boolean types" "C90" { target *-*-* } 63 } */
long void x27; /* { dg-error "both 'long' and 'void' in declaration specifiers" } */
short void x28; /* { dg-error "both 'short' and 'void' in declaration specifiers" } */
signed void x29; /* { dg-error "both 'signed' and 'void' in declaration specifiers" } */
unsigned void x30; /* { dg-error "both 'unsigned' and 'void' in declaration specifiers" } */
_Complex void x31; /* { dg-error "both 'complex' and 'void' in declaration specifiers" } */
-/* { dg-warning "ISO C90 does not support complex types" "C90" { target *-*-* } 66 } */
-/* { dg-warning "ISO C does not support plain 'complex' meaning 'double complex'" "complex" { target *-*-* } 66 } */
+/* { dg-warning "ISO C90 does not support complex types" "C90" { target *-*-* } 71 } */
+/* { dg-warning "ISO C does not support plain 'complex' meaning 'double complex'" "complex" { target *-*-* } 71 } */
long _Bool x32; /* { dg-error "both 'long' and '_Bool' in declaration specifiers" } */
+/* { dg-warning "ISO C90 does not support boolean types" "C90" { target *-*-* } 74 } */
short _Bool x33; /* { dg-error "both 'short' and '_Bool' in declaration specifiers" } */
+/* { dg-warning "ISO C90 does not support boolean types" "C90" { target *-*-* } 76 } */
signed _Bool x34; /* { dg-error "both 'signed' and '_Bool' in declaration specifiers" } */
+/* { dg-warning "ISO C90 does not support boolean types" "C90" { target *-*-* } 78 } */
unsigned _Bool x35; /* { dg-error "both 'unsigned' and '_Bool' in declaration specifiers" } */
+/* { dg-warning "ISO C90 does not support boolean types" "C90" { target *-*-* } 80 } */
_Complex _Bool x36; /* { dg-error "both 'complex' and '_Bool' in declaration specifiers" } */
-/* { dg-warning "ISO C90 does not support complex types" "C90" { target *-*-* } 73 } */
-/* { dg-warning "ISO C does not support plain 'complex' meaning 'double complex'" "complex" { target *-*-* } 73 } */
+/* { dg-warning "ISO C90 does not support complex types" "C90" { target *-*-* } 82 } */
+/* { dg-warning "ISO C90 does not support boolean types" "C90" { target *-*-* } 82 } */
+/* { dg-warning "ISO C does not support plain 'complex' meaning 'double complex'" "complex" { target *-*-* } 82 } */
long char x37; /* { dg-error "both 'long' and 'char' in declaration specifiers" } */
short char x38; /* { dg-error "both 'short' and 'char' in declaration specifiers" } */
long float x39; /* { dg-error "both 'long' and 'float' in declaration specifiers" } */
signed float x41; /* { dg-error "both 'signed' and 'float' in declaration specifiers" } */
unsigned float x42; /* { dg-error "both 'unsigned' and 'float' in declaration specifiers" } */
long long double x43; /* { dg-error "both 'long long' and 'double' in declaration specifiers" } */
-/* { dg-warning "ISO C90 does not support 'long long'" "C90" { target *-*-* } 82 } */
+/* { dg-warning "ISO C90 does not support 'long long'" "C90" { target *-*-* } 92 } */
short double x44; /* { dg-error "both 'short' and 'double' in declaration specifiers" } */
signed double x45; /* { dg-error "both 'signed' and 'double' in declaration specifiers" } */
unsigned double x46; /* { dg-error "both 'unsigned' and 'double' in declaration specifiers" } */
/* { dg-options "-Os -fdump-rtl-hoist" } */
-/* { dg-final { scan-rtl-dump "PRE/HOIST: end of bb .* copying expression" "hoist" { target { nonpic } } } } */
+/* The rtl hoist pass requires that the expression to be hoisted can
+ be assigned without clobbering cc. For a PLUS rtx on S/390 this
+ requires a load address instruction which is fine on 64 bit but
+ cannot be used on 31 bit since it does a 31 bit add only. */
+/* { dg-final { scan-rtl-dump "PRE/HOIST: end of bb .* copying expression" "hoist" { target { { ! s390-*-* } && nonpic } } } } */
/* { dg-final { cleanup-rtl-dump "hoist" } } */
#define BUF 100
-int a[BUF];
+long a[BUF];
-void com (int);
-void bar (int);
+void com (long);
+void bar (long);
-int foo (int x, int y, int z)
+long foo (long x, long y, long z)
{
/* "x+y" won't be hoisted if "-fira-hoist-pressure" is disabled,
because its rtx_cost is too small. */
/* { dg-options "-Os -fdump-rtl-hoist" } */
-/* { dg-final { scan-rtl-dump "PRE/HOIST: end of bb .* copying expression" "hoist" } } */
+/* The rtl hoist pass requires that the expression to be hoisted can
+ be assigned without clobbering cc. For a PLUS rtx on S/390 this
+ requires a load address instruction which is fine on 64 bit but
+ cannot be used on 31 bit since it does a 31 bit add only. */
+/* { dg-final { scan-rtl-dump "PRE/HOIST: end of bb .* copying expression" "hoist" { target { ! s390-*-* } } } } */
/* { dg-final { cleanup-rtl-dump "hoist" } } */
#define BUF 100
-int a[BUF];
+long a[BUF];
-void com (int);
-void bar (int);
+void com (long);
+void bar (long);
-int foo (int x, int y, int z)
+long foo (long x, long y, long z)
{
/* "x+y" won't be hoisted if "-fira-hoist-pressure" is disabled,
because its rtx_cost is too small. */
/* { dg-options "-Os -fdump-rtl-hoist" } */
-/* { dg-final { scan-rtl-dump "PRE/HOIST: end of bb .* copying expression" "hoist" } } */
+/* The rtl hoist pass requires that the expression to be hoisted can
+ be assigned without clobbering cc. For a PLUS rtx on S/390 this
+ requires a load address instruction which is fine on 64 bit but
+ cannot be used on 31 bit since it does a 31 bit add only. */
+/* { dg-final { scan-rtl-dump "PRE/HOIST: end of bb .* copying expression" "hoist" { target { ! s390-*-* } } } } */
/* { dg-final { cleanup-rtl-dump "hoist" } } */
#define BUF 100
-int a[BUF];
+long a[BUF];
-void com (int);
-void bar (int);
+void com (long);
+void bar (long);
-int foo (int x, int y, int z)
+long foo (long x, long y, long z)
{
/* "x+y" won't be hoisted if "-fira-hoist-pressure" is disabled,
because its rtx_cost is too small. */
--- /dev/null
+/* PR c/25801 */
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+int (*a)[];
+struct S *s;
+union U *u;
+enum E *e;
+
+void
+f (void)
+{
+ a++; /* { dg-error "increment of pointer to an incomplete type" } */
+ ++a; /* { dg-error "increment of pointer to an incomplete type" } */
+ a--; /* { dg-error "decrement of pointer to an incomplete type" } */
+ --a; /* { dg-error "decrement of pointer to an incomplete type" } */
+ a += 1; /* { dg-error "invalid use of array with unspecified bounds" } */
+ a -= 1; /* { dg-error "invalid use of array with unspecified bounds" } */
+ a - a; /* { dg-error "arithmetic on pointer to an incomplete type" } */
+
+ s++; /* { dg-error "increment of pointer to an incomplete type" } */
+ ++s; /* { dg-error "increment of pointer to an incomplete type" } */
+ s--; /* { dg-error "decrement of pointer to an incomplete type" } */
+ --s; /* { dg-error "decrement of pointer to an incomplete type" } */
+ s += 1; /* { dg-error "invalid use of undefined type" } */
+ s -= 1; /* { dg-error "invalid use of undefined type" } */
+ s - s; /* { dg-error "arithmetic on pointer to an incomplete type" } */
+
+ u++; /* { dg-error "increment of pointer to an incomplete type" } */
+ ++u; /* { dg-error "increment of pointer to an incomplete type" } */
+ u--; /* { dg-error "decrement of pointer to an incomplete type" } */
+ --u; /* { dg-error "decrement of pointer to an incomplete type" } */
+ u += 1; /* { dg-error "invalid use of undefined type" } */
+ u -= 1; /* { dg-error "invalid use of undefined type" } */
+ u - u; /* { dg-error "arithmetic on pointer to an incomplete type" } */
+
+ e++; /* { dg-error "increment of pointer to an incomplete type" } */
+ ++e; /* { dg-error "increment of pointer to an incomplete type" } */
+ e--; /* { dg-error "decrement of pointer to an incomplete type" } */
+ --e; /* { dg-error "decrement of pointer to an incomplete type" } */
+ e += 1; /* { dg-error "invalid use of undefined type" } */
+ e -= 1; /* { dg-error "invalid use of undefined type" } */
+ e - e; /* { dg-error "arithmetic on pointer to an incomplete type" } */
+}
--- /dev/null
+/* PR c/29467 */
+/* { dg-do compile } */
+/* { dg-options "-std=c89 -Wpedantic" } */
+
+_Bool b; /* { dg-warning "ISO C90 does not support boolean types" } */
+typedef _Bool B; /* { dg-warning "ISO C90 does not support boolean types" } */
+static _Bool sb; /* { dg-warning "ISO C90 does not support boolean types" } */
+
+_Bool /* { dg-warning "ISO C90 does not support boolean types" } */
+foo (_Bool bp) /* { dg-warning "ISO C90 does not support boolean types" } */
+{
+ _Bool bl; /* { dg-warning "ISO C90 does not support boolean types" } */
+}
--- /dev/null
+/* PR c/43245 */
+/* { dg-do compile } */
+/* { dg-options "-Wno-discarded-qualifiers" } */
+
+void
+foo (char *p)
+{
+}
+
+char *
+bar (void)
+{
+ const char *s = "foo";
+ char *s1 = s;
+ s1 = s;
+ foo (s);
+ return s;
+}
--- /dev/null
+/* PR c/56989 */
+/* { dg-do compile } */
+
+extern void voidf (void);
+extern int intf (void);
+
+int
+f (void)
+{
+ if (intf () < 0
+ || voidf () < 0) /* { dg-error "10:void value not ignored as it ought to be" } */
+ return 1;
+
+ if (voidf () < 0 /* { dg-error "7:void value not ignored as it ought to be" } */
+ || intf () < 0)
+ return 1;
+
+ return 0;
+}
--- /dev/null
+/* PR c/60257 */
+/* { dg-do compile } */
+/* { dg-options "-Wc++-compat -Woverride-init" } */
+/* { dg-prune-output ".*near initialization for.*" } */
+
+enum E1 { A };
+enum E2 { B };
+
+struct S
+{
+ enum E1 e: 3;
+};
+
+struct S s[] =
+{
+ { B } /* { dg-warning "5:enum conversion in initialization is invalid in C\[+\]\[+\]" } */
+};
+
+union U {
+ int i;
+ long long int l;
+};
+
+struct R {
+ int a;
+};
+
+void
+foo (int i)
+{
+ union U u = { .i = ++i, .l = 1 }; /* { dg-warning "32:initialized field with side-effects overwritten" } */
+ union U u2 = { .i = 1, .l = 3 }; /* { dg-warning "31:initialized field overwritten" } */
+ int a[] = { i++, [0] = 1 }; /* { dg-warning "26:initialized field with side-effects overwritten" } */
+ int a2[] = { i, [0] = 1 }; /* { dg-warning "25:initialized field overwritten" } */
+ struct R r = { 1, .a = 2 }; /* { dg-warning "26:initialized field overwritten" } */
+ struct R r2 = { ++i, .a = 2 }; /* { dg-warning "29:initialized field with side-effects overwritten" } */
+}
--- /dev/null
+/* PR c/60784 */
+/* { dg-do compile } */
+/* { dg-options "-Wextra -std=c99" } */
+
+struct A { int i, j; };
+struct B { struct A a; } b1 = { .a.i = 1, .a.j = 1 };
+struct B b2 = { .a.i = 1 };
+
+struct C { struct { int a, b; }; } c1 = { .a = 4, .b = 2 };
+struct C c2 = { .a = 4, .b = 2 };
+
+struct D { struct A a; };
+struct E { struct D d; };
+struct F { struct E e; } f1 = { .e.d.a.i = 8 };
+struct F f2 = { .e.d.a.i = 8, .e.d.a.j = 3 };
+
+struct G {
+ struct {
+ struct {
+ struct {
+ int a, b, c, d, e, f;
+ };
+ };
+ };
+} g = { .b = 2 };
--- /dev/null
+/* PR c/60915 */
+/* { dg-do compile } */
+
+void /* { dg-error "attributes should be specified before the declarator in a function definition" } */
+foo (void) __attribute__((__visibility__("default")))
+{
+}
--- /dev/null
+/* { dg-do compile } */
+
+int main (void)
+{
+ int a = 0;
+ unsigned b = (a * 64 & 192) | 63U;
+ return 0;
+}
-> "kill_elt->indx == b_elt->indx" in the second condition,
skipping the known-true "b_elt && kill_elt" in the second
condition. */
-/* { dg-final { scan-tree-dump-times "Threaded" 4 "dom1" { target logical_op_short_circuit xfail logical_op_short_circuit } } } */
+/* { dg-final { scan-tree-dump-times "Threaded" 4 "dom1" { target logical_op_short_circuit } } } */
/* { dg-final { cleanup-tree-dump "dom1" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_int } */
+
+#define N 512
+int a[N];
+int foo()
+{
+ int i, res = 0;
+ for (i=0; i<N; i++)
+ {
+ if (a[i] != 0)
+ res += 1;
+ }
+ return res;
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
+
--- /dev/null
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_int } */
+
+#define N 512
+int a[N], b[N];
+void foo(int k)
+{
+ int i, res = 0;
+ for (i=0; i<N; i++)
+ {
+ if (b[i] != 0)
+ res += b[i];
+ }
+ a[k] = sum;
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
+
--- /dev/null
+/* Test the `vuzpf32' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O1 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vuzpf32.x"
+
+/* { dg-final { scan-assembler-times "vuzp\.32\[ \t\]+\[dD\]\[0-9\]+, ?\[dD\]\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
--- /dev/null
+/* Test the `vuzpp16' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O1 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vuzpp16.x"
+
+/* { dg-final { scan-assembler-times "vuzp\.16\[ \t\]+\[dD\]\[0-9\]+, ?\[dD\]\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
--- /dev/null
+/* Test the `vuzpp8' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O1 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vuzpp8.x"
+
+/* { dg-final { scan-assembler-times "vuzp\.8\[ \t\]+\[dD\]\[0-9\]+, ?\[dD\]\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
--- /dev/null
+/* Test the `vuzpQf32' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O1 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vuzpqf32.x"
+
+/* { dg-final { scan-assembler-times "vuzp\.32\[ \t\]+\[qQ\]\[0-9\]+, ?\[qQ\]\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
--- /dev/null
+/* Test the `vuzpQp16' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O1 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vuzpqp16.x"
+
+/* { dg-final { scan-assembler-times "vuzp\.16\[ \t\]+\[qQ\]\[0-9\]+, ?\[qQ\]\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
--- /dev/null
+/* Test the `vuzpQp8' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O1 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vuzpqp8.x"
+
+/* { dg-final { scan-assembler-times "vuzp\.8\[ \t\]+\[qQ\]\[0-9\]+, ?\[qQ\]\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
--- /dev/null
+/* Test the `vuzpQs16' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O1 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vuzpqs16.x"
+
+/* { dg-final { scan-assembler-times "vuzp\.16\[ \t\]+\[qQ\]\[0-9\]+, ?\[qQ\]\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
--- /dev/null
+/* Test the `vuzpQs32' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O1 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vuzpqs32.x"
+
+/* { dg-final { scan-assembler-times "vuzp\.32\[ \t\]+\[qQ\]\[0-9\]+, ?\[qQ\]\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
--- /dev/null
+/* Test the `vuzpQs8' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O1 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vuzpqs8.x"
+
+/* { dg-final { scan-assembler-times "vuzp\.8\[ \t\]+\[qQ\]\[0-9\]+, ?\[qQ\]\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
--- /dev/null
+/* Test the `vuzpQu16' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O1 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vuzpqu16.x"
+
+/* { dg-final { scan-assembler-times "vuzp\.16\[ \t\]+\[qQ\]\[0-9\]+, ?\[qQ\]\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
--- /dev/null
+/* Test the `vuzpQu32' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O1 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vuzpqu32.x"
+
+/* { dg-final { scan-assembler-times "vuzp\.32\[ \t\]+\[qQ\]\[0-9\]+, ?\[qQ\]\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
--- /dev/null
+/* Test the `vuzpQu8' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O1 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vuzpqu8.x"
+
+/* { dg-final { scan-assembler-times "vuzp\.8\[ \t\]+\[qQ\]\[0-9\]+, ?\[qQ\]\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
--- /dev/null
+/* Test the `vuzps16' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O1 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vuzps16.x"
+
+/* { dg-final { scan-assembler-times "vuzp\.16\[ \t\]+\[dD\]\[0-9\]+, ?\[dD\]\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
--- /dev/null
+/* Test the `vuzps32' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O1 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vuzps32.x"
+
+/* { dg-final { scan-assembler-times "vuzp\.32\[ \t\]+\[dD\]\[0-9\]+, ?\[dD\]\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
--- /dev/null
+/* Test the `vuzps8' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O1 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vuzps8.x"
+
+/* { dg-final { scan-assembler-times "vuzp\.8\[ \t\]+\[dD\]\[0-9\]+, ?\[dD\]\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
--- /dev/null
+/* Test the `vuzpu16' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O1 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vuzpu16.x"
+
+/* { dg-final { scan-assembler-times "vuzp\.16\[ \t\]+\[dD\]\[0-9\]+, ?\[dD\]\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
--- /dev/null
+/* Test the `vuzpu32' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O1 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vuzpu32.x"
+
+/* { dg-final { scan-assembler-times "vuzp\.32\[ \t\]+\[dD\]\[0-9\]+, ?\[dD\]\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
--- /dev/null
+/* Test the `vuzpu8' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O1 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vuzpu8.x"
+
+/* { dg-final { scan-assembler-times "vuzp\.8\[ \t\]+\[dD\]\[0-9\]+, ?\[dD\]\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
/* { dg-do run { target { powerpc*-*-linux* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */
-/* { dg-require-effective-target vsx_hw } */
-/* { dg-options "-O2" } */
+/* { dg-require-effective-target powerpc_fprs } */
+/* { dg-options "-O2 -mhard-float" } */
#include <stddef.h>
#include <stdlib.h>
/* { dg-do run { target { powerpc*-*-linux* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */
-/* { dg-require-effective-target vsx_hw } */
-/* { dg-options "-O2" } */
+/* { dg-require-effective-target dfprt } */
+/* { dg-options "-O2 -mhard-dfp" } */
#include <stddef.h>
#include <stdlib.h>
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z900 -pg" } */
+
+int
+foo ()
+{
+}
+/* Make sure no stack frame is generated. */
+/* { dg-final { scan-assembler-not "ahi" { target s390-*-* } } } */
+/* { dg-final { scan-assembler-not "aghi" { target s390x-*-* } } } */
/* Compiled and linked by bind_c.f90. */
#include <stdlib.h>
+#include <stdbool.h>
-void subtest (_Bool, int *);
+void subtest (bool, int *);
void
-c_proc (_Bool present, int *val)
+c_proc (bool present, int *val)
{
int val2;
if (!present && val)
#define NUM_ELEMS 10
-void test_scalar(_Bool *my_c_bool_ptr);
-void test_array(_Bool *my_bool_array, int num_elems);
+void test_scalar(bool *my_c_bool_ptr);
+void test_array(bool *my_bool_array, int num_elems);
int main(int argc, char **argv)
{
- _Bool my_bool = true;
- _Bool my_bool_array[NUM_ELEMS];
+ bool my_bool = true;
+ bool my_bool_array[NUM_ELEMS];
int i;
test_scalar(&my_bool);
--- /dev/null
+! { dg-do run }
+!
+! Based on coarray_lib_token_4.f90 but checking whether the bounds
+! are correctly handled.
+!
+program test_caf
+ implicit none
+ integer, allocatable :: A(:)[:]
+ integer, save :: B(3)[*]
+ integer :: i
+
+ allocate (A(3)[*])
+ A = [1, 2, 3 ]
+ B = [9, 7, 4 ]
+ call foo (A, A, test=1)
+ call foo (A(2:3), B, test=2)
+ call foo (B, A, test=3)
+contains
+ subroutine foo(x, y, test)
+ integer :: x(:)[*]
+ integer, contiguous :: y(:)[*]
+ integer :: test
+ integer :: i, j
+ call bar (x)
+ call expl (y)
+ i = lcobound(x, dim=1)
+ j = ucobound(x, dim=1)
+ if (i /= 1 .or. j /= num_images()) call abort()
+ i = lcobound(y, dim=1)
+ j = ucobound(y, dim=1)
+ if (i /= 1 .or. j /= num_images()) call abort()
+ end subroutine foo
+
+ subroutine bar(y)
+ integer :: y(:)[*]
+ integer :: i, j
+ i = lcobound(y, dim=1)
+ j = ucobound(y, dim=1)
+ if (i /= 1 .or. j /= num_images()) call abort()
+ end subroutine bar
+
+ subroutine expl(z)
+ integer :: z(*)[*]
+ integer :: i, j
+ i = lcobound(z, dim=1)
+ j = ucobound(z, dim=1)
+ if (i /= 1 .or. j /= num_images()) call abort()
+ end subroutine expl
+end program test_caf
--- /dev/null
+! { dg-do compile }
+! { dg-options "-fcoarray=lib -fdump-tree-original" }
+!
+
+ implicit none
+ real :: x(2)[*]
+ call bar(x)
+contains
+ subroutine bar(x)
+ integer :: mylcobound, myucobound, mylbound, mythis_image
+ real :: x(2)[5:*]
+ mylcobound = lcobound(x,dim=1)
+ myucobound = ucobound(x,dim=1)
+ mylbound = lbound(x,dim=1)
+ mythis_image = this_image()
+ end subroutine bar
+end
+
+! { dg-final { scan-tree-dump-times "bar \\(real\\(kind=4\\)\\\[2\\\] \\* restrict x, void \\* restrict caf_token.., integer\\(kind=\[48\]\\) caf_offset..\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "mylcobound = 5;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "parm...dim\\\[1\\\].lbound = 5;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "myucobound =\[^\n\r\]* parm...dim\\\[1\\\].lbound \\+ \[^\n\r]*_gfortran_caf_num_images \\(0, -1\\).? \\+ -?\[0-9\]+\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "mylbound = 1;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "mythis_image = _gfortran_caf_this_image \\(0\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "bar \\(x, caf_token.., 0\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "_gfortran_caf_init \\(&argc, &argv\\);" 1 "original" } }
+! { dg-final { cleanup-tree-dump "original" } }
--- /dev/null
+! { dg-do compile }
+! { dg-options "-fcoarray=lib -fdump-tree-original" }
+!
+
+ implicit none
+ real :: x(2)[*]
+ call bar(x)
+contains
+ subroutine bar(x)
+ integer :: mylcobound, myucobound, mylbound, mythis_image
+ real :: x(:)[5:*]
+ mylcobound = lcobound(x,dim=1)
+ myucobound = ucobound(x,dim=1)
+ mylbound = lbound(x,dim=1)
+ mythis_image = this_image()
+ end subroutine bar
+end
+
+! { dg-final { scan-tree-dump-times "bar \\(struct array1_real\\(kind=4\\) & restrict x, void \\* restrict caf_token.., integer\\(kind=\[48\]\\) caf_offset..\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "mylcobound = 5;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "parm...dim\\\[1\\\].lbound = 5;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "myucobound =\[^\n\r\]* parm...dim\\\[1\\\].lbound \\+ \[^\n\r\]*_gfortran_caf_num_images \\(0, -1\\).? \\+ -?\[0-9\]+\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "mylbound = parm...dim\\\[0\\\].stride >= 0 && parm...dim\\\[0\\\].ubound >= parm...dim\\\[0\\\].lbound \\|\\| parm...dim\\\[0\\\].stride < 0 \\?\[^\n\r\]* parm...dim\\\[0\\\].lbound : 1;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "mythis_image = _gfortran_caf_this_image \\(0\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "bar \\(&parm.\[0-9\]+, caf_token.\[0-9\]+, \\(integer\\(kind=\[48\]\\)\\) parm.\[0-9\]+.data - \\(integer\\(kind=\[48\]\\)\\) x\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "_gfortran_caf_init \\(&argc, &argv\\);" 1 "original" } }
+! { dg-final { cleanup-tree-dump "original" } }
! { dg-final { scan-tree-dump-times "expl \\(integer\\(kind=4\\).0:. . restrict z, void . restrict caf_token.\[0-9\]+, integer\\(kind=.\\) caf_offset.\[0-9\]+\\)" 1 "original" } }
!
-! { dg-final { scan-tree-dump-times "bar \\(struct array2_integer\\(kind=4\\) & restrict y, void . restrict caf_token.\[0-9\]+, integer\\(kind=.\\) caf_offset.\[0-9\]+\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "bar \\(struct array1_integer\\(kind=4\\) & restrict y, void . restrict caf_token.\[0-9\]+, integer\\(kind=.\\) caf_offset.\[0-9\]+\\)" 1 "original" } }
!
-! { dg-final { scan-tree-dump-times "foo \\(struct array2_integer\\(kind=4\\) & restrict x, struct array2_integer\\(kind=4\\) & restrict y, integer\\(kind=4\\) & restrict test, void . restrict caf_token.\[0-9\]+, integer\\(kind=.\\) caf_offset.\[0-9\]+, void . restrict caf_token.\[0-9\]+, integer\\(kind=.\\) caf_offset.\[0-9\]+\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "foo \\(struct array1_integer\\(kind=4\\) & restrict x, struct array1_integer\\(kind=4\\) & restrict y, integer\\(kind=4\\) & restrict test, void . restrict caf_token.\[0-9\]+, integer\\(kind=.\\) caf_offset.\[0-9\]+, void . restrict caf_token.\[0-9\]+, integer\\(kind=.\\) caf_offset.\[0-9\]+\\)" 1 "original" } }
!
! { dg-final { scan-tree-dump-times "bar \\(&parm.\[0-9\]+, caf_token.\[0-9\]+, \\(\\(integer\\(kind=.\\)\\) parm.\[0-9\]+.data - \\(integer\\(kind=.\\)\\) x.\[0-9\]+\\) \\+ caf_offset.\[0-9\]+\\);" 1 "original" } }
!
--- /dev/null
+! { dg-do compile }
+! { dg-options "-fcoarray=lib -fdump-tree-original" }
+
+subroutine test(i)
+type t
+ real, allocatable :: x[:]
+end type t
+
+interface
+ subroutine sub(y)
+ import
+ real :: y[*]
+ end subroutine sub
+end interface
+
+integer :: i
+type(t), save :: var
+allocate(var%x[*])
+call sub(var%x)
+end subroutine test
+
+! { dg-final { scan-tree-dump-times "sub \\(\\(real\\(kind=4\\) \\*\\) var.x.data, var.x.token, 0\\);" 1 "original" } }
+! { dg-final { cleanup-tree-dump "original" } }
--- /dev/null
+! { dg-do compile }
+! { dg-options "-fcoarray=lib -fdump-tree-original" }
+
+subroutine test(x)
+type t
+ real, allocatable :: x[:]
+end type t
+
+class(t) :: x
+allocate(x%x[*])
+end subroutine test
+
+! { dg-final { scan-tree-dump-times "x->_data->x.data = _gfortran_caf_register \\(4, 1, &x->_data->x.token, 0B, 0B, 0\\);" 1 "original" } }
+! { dg-final { cleanup-tree-dump "original" } }
--- /dev/null
+! { dg-do compile }
+! { dg-options "-fcoarray=lib -fdump-tree-original" }
+!
+ implicit none
+ type t
+ end type t
+ class(t), allocatable :: y[:]
+ call bar()
+ call foo(y)
+contains
+ subroutine bar(x)
+ class(t), optional :: x[*]
+ end subroutine bar
+ subroutine foo(x)
+ class(t) :: x[*]
+ end subroutine foo
+end
+! { dg-final { scan-tree-dump-times "foo \\(struct __class_MAIN___T_0_1t & restrict x, void \\* restrict caf_token.., integer\\(kind=\[48\]\\) caf_offset..\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "bar \\(struct __class_MAIN___T_0_1t \\* x, void \\* restrict caf_token.., integer\\(kind=\[48\]\\) caf_offset..\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "bar \\(0B, 0B, 0\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "foo \\(&class.., y._data._data.token, \\(integer\\(kind=\[48\]\\)\\) class..._data.data - \\(integer\\(kind=\[48\]\\)\\) y._data._data.data\\);" 1 "original" } }
+! { dg-final { cleanup-tree-dump "original" } }
--- /dev/null
+! { dg-do compile }
+! { dg-options "-fcoarray=lib -fdump-tree-original" }
+!
+ implicit none
+ type t
+ end type t
+ class(t), allocatable :: y(:)[:]
+ call bar()
+ call foo(y)
+contains
+ subroutine bar(x)
+ class(t), optional :: x(:)[*]
+ end subroutine bar
+ subroutine foo(x)
+ class(t) :: x(:)[*]
+ end subroutine foo
+end
+! { dg-final { scan-tree-dump-times "foo \\(struct __class_MAIN___T_1_1t & restrict x, void \\* restrict caf_token.., integer\\(kind=\[48\]\\) caf_offset..\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "bar \\(struct __class_MAIN___T_1_1t \\* x, void \\* restrict caf_token.., integer\\(kind=\[48\]\\) caf_offset..\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "bar \\(0B, 0B, 0\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "foo \\(&class.., y._data._data.token, \\(integer\\(kind=\[48\]\\)\\) class..._data.data - \\(integer\\(kind=\[48\]\\)\\) y._data._data.data\\);" 1 "original" } }
+! { dg-final { cleanup-tree-dump "original" } }
--- /dev/null
+! { dg-do compile }
+! { dg-options "-fcoarray=lib -fdump-tree-original" }
+!
+ implicit none
+ type t
+ end type t
+ class(t), allocatable :: y(:)[:]
+ call bar()
+ call foo(y)
+contains
+ subroutine bar(x)
+ class(t), optional :: x(2)[*]
+ end subroutine bar
+ subroutine foo(x)
+ class(t) :: x(2)[*]
+ end subroutine foo
+end
+! { dg-final { scan-tree-dump-times "foo \\(struct __class_MAIN___T_1_1t & restrict x, void \\* restrict caf_token.., integer\\(kind=\[48\]\\) caf_offset..\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "bar \\(struct __class_MAIN___T_1_1t \\* x, void \\* restrict caf_token.., integer\\(kind=\[48\]\\) caf_offset..\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "bar \\(0B, 0B, 0\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "foo \\(&class.., y._data._data.token, \\(integer\\(kind=\[48\]\\)\\) class..._data.data - \\(integer\\(kind=\[48\]\\)\\) y._data._data.data\\);" 1 "original" } }
+! { dg-final { cleanup-tree-dump "original" } }
lappend del "[file rootname [file tail [lindex $p 1]]].o"
}
set dg-do-what-default "link"
- set go_compile_args $del
- go-torture-execute [lrange $last 1 end]
+ set go_compile_args ""
+ append go_compile_args [lrange $last 2 end]
+ append go_compile_args $del
+ go-torture-execute [lindex $last 1]
foreach f $del {
file delete $f
}
return first_edge->src;
}
+/* Returns true if def-stmt for phi argument ARG is simple increment/decrement
+ which is in predicated basic block.
+ In fact, the following PHI pattern is searching:
+ loop-header:
+ reduc_1 = PHI <..., reduc_2>
+ ...
+ if (...)
+ reduc_3 = ...
+ reduc_2 = PHI <reduc_1, reduc_3>
+
+ REDUC, OP0 and OP1 contain reduction stmt and its operands. */
+
+static bool
+is_cond_scalar_reduction (gimple phi, gimple *reduc,
+ tree *op0, tree *op1)
+{
+ tree lhs, r_op1, r_op2;
+ tree arg_0, arg_1;
+ gimple stmt;
+ gimple header_phi = NULL;
+ enum tree_code reduction_op;
+ struct loop *loop = gimple_bb (phi)->loop_father;
+ edge latch_e = loop_latch_edge (loop);
+
+ arg_0 = PHI_ARG_DEF (phi, 0);
+ arg_1 = PHI_ARG_DEF (phi, 1);
+ if (TREE_CODE (arg_0) != SSA_NAME || TREE_CODE (arg_1) != SSA_NAME)
+ return false;
+
+ if (gimple_code (SSA_NAME_DEF_STMT (arg_0)) == GIMPLE_PHI)
+ {
+ lhs = arg_1;
+ header_phi = SSA_NAME_DEF_STMT (arg_0);
+ stmt = SSA_NAME_DEF_STMT (arg_1);
+ }
+ else if (gimple_code (SSA_NAME_DEF_STMT (arg_1)) == GIMPLE_PHI)
+ {
+ lhs = arg_0;
+ header_phi = SSA_NAME_DEF_STMT (arg_1);
+ stmt = SSA_NAME_DEF_STMT (arg_0);
+ }
+ else
+ return false;
+ if (gimple_bb (header_phi) != loop->header)
+ return false;
+
+ if (PHI_ARG_DEF_FROM_EDGE (header_phi, latch_e) != PHI_RESULT (phi))
+ return false;
+
+ if (gimple_code (stmt) != GIMPLE_ASSIGN
+ || gimple_has_volatile_ops (stmt))
+ return false;
+
+ if (!is_predicated (gimple_bb (stmt)))
+ return false;
+
+ if (!has_single_use (lhs))
+ return false;
+
+ reduction_op = gimple_assign_rhs_code (stmt);
+ if (reduction_op != PLUS_EXPR && reduction_op != MINUS_EXPR)
+ return false;
+ r_op1 = gimple_assign_rhs1 (stmt);
+ r_op2 = gimple_assign_rhs2 (stmt);
+
+ /* Make R_OP1 to hold reduction variable. */
+ if (r_op2 == PHI_RESULT (header_phi)
+ && reduction_op == PLUS_EXPR)
+ {
+ tree tmp = r_op1;
+ r_op1 = r_op2;
+ r_op2 = tmp;
+ }
+ else if (r_op1 != PHI_RESULT (header_phi))
+ return false;
+
+ *op0 = r_op1; *op1 = r_op2;
+ *reduc = stmt;
+ return true;
+}
+
+/* Converts conditional scalar reduction into unconditional form, e.g.
+ bb_4
+ if (_5 != 0) goto bb_5 else goto bb_6
+ end_bb_4
+ bb_5
+ res_6 = res_13 + 1;
+ end_bb_5
+ bb_6
+ # res_2 = PHI <res_13(4), res_6(5)>
+ end_bb_6
+
+ will be converted into sequence
+ _ifc__1 = _5 != 0 ? 1 : 0;
+ res_2 = res_13 + _ifc__1;
+ Argument SWAP tells that arguments of conditional expression should be
+ swapped.
+ Returns rhs of resulting PHI assignment. */
+
+static tree
+convert_scalar_cond_reduction (gimple reduc, gimple_stmt_iterator *gsi,
+ tree cond, tree op0, tree op1, bool swap)
+{
+ gimple_stmt_iterator stmt_it;
+ gimple new_assign;
+ tree rhs;
+ tree rhs1 = gimple_assign_rhs1 (reduc);
+ tree tmp = make_temp_ssa_name (TREE_TYPE (rhs1), NULL, "_ifc_");
+ tree c;
+ tree zero = build_zero_cst (TREE_TYPE (rhs1));
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Found cond scalar reduction.\n");
+ print_gimple_stmt (dump_file, reduc, 0, TDF_SLIM);
+ }
+
+ /* Build cond expression using COND and constant operand
+ of reduction rhs. */
+ c = fold_build_cond_expr (TREE_TYPE (rhs1),
+ unshare_expr (cond),
+ swap ? zero : op1,
+ swap ? op1 : zero);
+
+ /* Create assignment stmt and insert it at GSI. */
+ new_assign = gimple_build_assign (tmp, c);
+ gsi_insert_before (gsi, new_assign, GSI_SAME_STMT);
+ /* Build rhs for unconditional increment/decrement. */
+ rhs = fold_build2 (gimple_assign_rhs_code (reduc),
+ TREE_TYPE (rhs1), op0, tmp);
+
+ /* Delete original reduction stmt. */
+ stmt_it = gsi_for_stmt (reduc);
+ gsi_remove (&stmt_it, true);
+ release_defs (reduc);
+ return rhs;
+}
+
/* Replace a scalar PHI node with a COND_EXPR using COND as condition.
This routine does not handle PHI nodes with more than two
arguments.
else
{
tree arg_0, arg_1;
+ tree op0, op1;
+ gimple reduc;
+
/* Use condition that is not TRUTH_NOT_EXPR in conditional modify expr. */
if (EDGE_PRED (bb, 1)->src == true_bb)
{
arg_0 = gimple_phi_arg_def (phi, 0);
arg_1 = gimple_phi_arg_def (phi, 1);
}
-
- /* Build new RHS using selected condition and arguments. */
- rhs = fold_build_cond_expr (TREE_TYPE (res), unshare_expr (cond),
- arg_0, arg_1);
+ if (is_cond_scalar_reduction (phi, &reduc, &op0, &op1))
+ /* Convert reduction stmt into vectorizable form. */
+ rhs = convert_scalar_cond_reduction (reduc, gsi, cond, op0, op1,
+ true_bb != gimple_bb (reduc));
+ else
+ /* Build new RHS using selected condition and arguments. */
+ rhs = fold_build_cond_expr (TREE_TYPE (res), unshare_expr (cond),
+ arg_0, arg_1);
}
new_stmt = gimple_build_assign (res, rhs);
}
}
-/* For each PHI in BB, copy the argument associated with SRC_E to TGT_E. */
+/* Given ssa_name DEF, backtrack jump threading PATH from node IDX
+ to see if it has constant value in a flow sensitive manner. Set
+ LOCUS to location of the constant phi arg and return the value.
+ Return DEF directly if either PATH or idx is ZERO. */
+
+static tree
+get_value_locus_in_path (tree def, vec<jump_thread_edge *> *path,
+ basic_block bb, int idx, source_location *locus)
+{
+ tree arg;
+ gimple def_phi;
+ basic_block def_bb;
+
+ if (path == NULL || idx == 0)
+ return def;
+
+ def_phi = SSA_NAME_DEF_STMT (def);
+ if (gimple_code (def_phi) != GIMPLE_PHI)
+ return def;
+
+ def_bb = gimple_bb (def_phi);
+ /* Don't propagate loop invariants into deeper loops. */
+ if (!def_bb || bb_loop_depth (def_bb) < bb_loop_depth (bb))
+ return def;
+
+ /* Backtrack jump threading path from IDX to see if def has constant
+ value. */
+ for (int j = idx - 1; j >= 0; j--)
+ {
+ edge e = (*path)[j]->e;
+ if (e->dest == def_bb)
+ {
+ arg = gimple_phi_arg_def (def_phi, e->dest_idx);
+ if (is_gimple_min_invariant (arg))
+ {
+ *locus = gimple_phi_arg_location (def_phi, e->dest_idx);
+ return arg;
+ }
+ break;
+ }
+ }
+
+ return def;
+}
+
+/* For each PHI in BB, copy the argument associated with SRC_E to TGT_E.
+ Try to backtrack jump threading PATH from node IDX to see if the arg
+ has constant value, copy constant value instead of argument itself
+ if yes. */
static void
-copy_phi_args (basic_block bb, edge src_e, edge tgt_e)
+copy_phi_args (basic_block bb, edge src_e, edge tgt_e,
+ vec<jump_thread_edge *> *path, int idx)
{
gimple_stmt_iterator gsi;
int src_indx = src_e->dest_idx;
for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
gimple phi = gsi_stmt (gsi);
+ tree def = gimple_phi_arg_def (phi, src_indx);
source_location locus = gimple_phi_arg_location (phi, src_indx);
- add_phi_arg (phi, gimple_phi_arg_def (phi, src_indx), tgt_e, locus);
+
+ if (TREE_CODE (def) == SSA_NAME
+ && !virtual_operand_p (gimple_phi_result (phi)))
+ def = get_value_locus_in_path (def, path, bb, idx, &locus);
+
+ add_phi_arg (phi, def, tgt_e, locus);
}
}
edges. The copy is NEW_BB. Every PHI node in every direct successor of
ORIG_BB has a new argument associated with edge from NEW_BB to the
successor. Initialize the PHI argument so that it is equal to the PHI
- argument associated with the edge from ORIG_BB to the successor. */
+ argument associated with the edge from ORIG_BB to the successor.
+ PATH and IDX are used to check if the new PHI argument has constant
+ value in a flow sensitive manner. */
static void
-update_destination_phis (basic_block orig_bb, basic_block new_bb)
+update_destination_phis (basic_block orig_bb, basic_block new_bb,
+ vec<jump_thread_edge *> *path, int idx)
{
edge_iterator ei;
edge e;
FOR_EACH_EDGE (e, ei, orig_bb->succs)
{
edge e2 = find_edge (new_bb, e->dest);
- copy_phi_args (e->dest, e, e2);
+ copy_phi_args (e->dest, e, e2, path, idx);
}
}
destination.
Add an additional argument to any PHI nodes at the single
- destination. */
+ destination. IDX is the start node in jump threading path
+ we start to check to see if the new PHI argument has constant
+ value along the jump threading path. */
static void
create_edge_and_update_destination_phis (struct redirection_data *rd,
- basic_block bb)
+ basic_block bb, int idx)
{
edge e = make_edge (bb, rd->path->last ()->e->dest, EDGE_FALLTHRU);
from the duplicate block, then we will need to add a new argument
to them. The argument should have the same value as the argument
associated with the outgoing edge stored in RD. */
- copy_phi_args (e->dest, rd->path->last ()->e, e);
+ copy_phi_args (e->dest, rd->path->last ()->e, e, rd->path, idx);
}
/* Look through PATH beginning at START and return TRUE if there are
ssa_fix_duplicate_block_edges (struct redirection_data *rd,
ssa_local_info_t *local_info)
{
+ bool multi_incomings = (rd->incoming_edges->next != NULL);
edge e = rd->incoming_edges->e;
vec<jump_thread_edge *> *path = THREAD_PATH (e);
edge e2;
/* This updates the PHIs at the destination of the duplicate
- block. */
- update_destination_phis (local_info->bb, rd->dup_blocks[count]);
+ block. Pass 0 instead of i if we are threading a path which
+ has multiple incoming edges. */
+ update_destination_phis (local_info->bb, rd->dup_blocks[count],
+ path, multi_incomings ? 0 : i);
/* Find the edge from the duplicate block to the block we're
threading through. That's the edge we want to redirect. */
case), then the PHIs in the target already have the correct
arguments. */
if (e2 == victim)
- copy_phi_args (e2->dest, path->last ()->e, e2);
+ copy_phi_args (e2->dest, path->last ()->e, e2,
+ path, multi_incomings ? 0 : i);
}
else
{
else if ((*path)[i]->type == EDGE_COPY_SRC_BLOCK)
{
remove_ctrl_stmt_and_useless_edges (rd->dup_blocks[count], NULL);
- create_edge_and_update_destination_phis (rd, rd->dup_blocks[count]);
+ create_edge_and_update_destination_phis (rd, rd->dup_blocks[count],
+ multi_incomings ? 0 : i);
if (count == 1)
single_succ_edge (rd->dup_blocks[1])->aux = NULL;
count++;
create_block_for_threading (bb, &rd, 0);
remove_ctrl_stmt_and_useless_edges (rd.dup_blocks[0], NULL);
- create_edge_and_update_destination_phis (&rd, rd.dup_blocks[0]);
+ create_edge_and_update_destination_phis (&rd, rd.dup_blocks[0], 0);
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, " Threaded jump %d --> %d to %d\n",