From: monabuilder Date: Tue, 23 Dec 2008 07:08:48 +0000 (+0000) Subject: r383@cf-ppc-macosx: monabuilder | 2008-12-23 16:04:56 +0900 X-Git-Url: http://git.sourceforge.jp/view?a=commitdiff_plain;h=72fc05919d785bb3cfbaf8521a45d60f42106daa;p=pf3gnuchains%2Fpf3gnuchains3x.git r383@cf-ppc-macosx: monabuilder | 2008-12-23 16:04:56 +0900 smerge with /gcc.gnu.org/trunk/ git-svn-id: svn+ssh://svn.sourceforge.jp/svnroot/pf3gnuchains/trunk@14 dabda00f-5829-0410-a8ea-e5f24da5a5ee --- diff --git a/ChangeLog b/ChangeLog index a49ff418c9..ee366db901 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2008-12-08 Luis Machado + + * MAINTAINERS: Add myself to the write after approval list. + 2008-12-04 Jack Howarth * configure.ac: Add double brackets on darwin[912]. diff --git a/MAINTAINERS b/MAINTAINERS index 7d342e3c85..5d38f8768d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -381,6 +381,7 @@ Manuel L Martin v. Löwis loewis@informatik.hu-berlin.de H.J. Lu hjl.tools@gmail.com Xinliang David Li davidxl@google.com +Luis Machado luisgpm@br.ibm.com William Maddox maddox@google.com Ziga Mahkovec ziga.mahkovec@klika.si Simon Martin simartin@users.sourceforge.net diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0c889a1824..c386069bd3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,577 @@ +2008-12-12 Dwarakanath Rajagopal + + * config/i386/x86intrin.h: New header file to support all x86 + intrinsics + * config.gcc (extra_headers): For x86 and x86-64, add x86intrin.h + +2008-12-12 H.J. Lu + + PR target/38402 + * gcc/doc/md.texi: Remove Y and document Yz, Y2, Yi and Ym + constraints for x86. + +2008-12-12 Andreas Schwab + + * cfgrtl.c (rtl_verify_flow_info_1): Don't apply BLOCK_FOR_INSN on + a BARRIER insn. + +2008-12-12 Uros Bizjak + + * config/alpha/sync.md (memory_barrier): Remove mem:BLK from operands. + Use Pmode for scratch reg. + (*mb_internal): Use (match_dup 0) for unspec operand. + +2008-12-12 Alexandre Oliva + + * tree-vrp.c (extract_range_from_binary_expr): Don't shift by + floor_log2 of zero. Negate widened zero. + +2008-12-12 Ben Elliston + + * config/fp-bit.c (nan): Rename from this .. + (makenan): .. to this. + +2008-12-11 Adam Nemet + + * config/mips/mips.md (*branch_bit, + *branch_bit_inverted): Renumber operands so that the + label becomes operands[1]. + +2008-12-11 Harsha Jagasia + + PR tree-optimization/38446 + * graphite.c (register_bb_in_sese): New. + (bb_in_sese_p): Check if bb belongs to sese region by explicitly + looking at the bbs in the region. + * graphite.h (sese): Add region_basic_blocks pointer set to + structure and initialize at the time of defining new scop. + +2008-12-11 Tobias Grosser + + * graphite.c (new_graphite_bb): Initialize GBB_STATIC_SCHEDULE. + (find_params_in_bb): Do not free data refs. + (free_graphite_bb): Add FIXME on disabled free_data_refs. + +2008-12-11 Sebastian Pop + + * graphite.c (struct ivtype_map_elt): New. + (debug_ivtype_elt, debug_ivtype_map_1, debug_ivtype_map, + new_ivtype_map_elt, ivtype_map_elt_info, eq_ivtype_map_elts, + gcc_type_for_cloog_iv): New. + (loop_iv_stack_patch_for_consts): Use the type of the induction + variable from the original loop, except for the automatically + generated loops, i.e., in the case of a strip-mined loop, in + which case there is no original loop: in that case just use + integer_type_node. + (new_graphite_bb): Initialize GBB_CLOOG_IV_TYPES. + (free_graphite_bb): Free GBB_CLOOG_IV_TYPES. + (clast_name_to_gcc): Accept params to be NULL. + (clast_to_gcc_expression): Take an extra parameter for the type. + Convert to that type all the expressions built by this function. + (gcc_type_for_clast_expr, gcc_type_for_clast_eq): New. + (graphite_translate_clast_equation): Compute the type of the + clast_equation before translating its LHS and RHS. + (clast_get_body_of_loop, gcc_type_for_iv_of_clast_loop): New. + (graphite_create_new_loop): Compute the type of the induction + variable before translating the lower and upper bounds and before + creating the induction variable. + (rename_variables_from_edge, rename_phis_end_scop): New. + (copy_bb_and_scalar_dependences): Call rename_phis_end_scop. + (sese_add_exit_phis_edge): Do not use integer_zero_node. + (find_cloog_iv_in_expr, compute_cloog_iv_types_1, + compute_cloog_iv_types): New. + (gloog): Call compute_cloog_iv_types before starting the + translation of the clast. + + * graphite.h (struct graphite_bb): New field cloog_iv_types. + (GBB_CLOOG_IV_TYPES): New. + (debug_ivtype_map): Declared. + (oldiv_for_loop): New. + +2008-12-10 Tobias Grosser + + PR middle-end/38459 + * graphite.c (new_scop): Initialize SCOP_ADD_PARAMS. + (param_index): Assert if parameter is not know after parameter + detection. + (find_params_in_bb): Detect params directly in GBB_CONDITIONS. + (find_scop_parameters): Mark, that we have finished parameter + detection. + (graphite_transform_loops): Move condition detection before parameter + detection. + * graphite.h (struct scop): Add SCOP_ADD_PARAMS. + +2008-12-11 John David Anglin + + PR testsuite/35677 + * emutls.c (__emutls_get_address): Make sure offset is really zero + before initializing the object's offset. + +2008-12-11 Jakub Jelinek + + PR c++/38253 + * gimplify.c (gimplify_init_constructor): Don't force constructor + into memory if there is just one nonzero element. + +2008-12-11 Sebastian Pop + + Fix testsuite/gfortran.dg/graphite/id-4.f90. + * graphite.c (scan_tree_for_params): Do not compute the multiplicand + when not needed. + +2008-12-11 Sebastian Pop + + * graphite.c (build_scops_1): Initialize open_scop.exit + and sinfo.last. + +2008-12-11 Sebastian Pop + Jan Sjodin + Harsha Jagasia + + PR middle-end/37852 + PR middle-end/37883 + PR middle-end/37928 + PR middle-end/37980 + PR middle-end/38038 + PR middle-end/38039 + PR middle-end/38073 + PR middle-end/38083 + PR middle-end/38125 + + * tree-phinodes.c (remove_phi_nodes): New, extracted from... + * tree-cfg.c (remove_phi_nodes_and_edges_for_unreachable_block): + ... here. + * tree-flow.h (remove_phi_nodes, canonicalize_loop_ivs): Declared. + * Makefile.in (graphite.o): Depend on value-prof.h. + (graphite.o-warn): Removed -Wno-error. + * tree-parloops.c (canonicalize_loop_ivs): Allow reduction_list + to be a NULL pointer. Call update_stmt. Return the newly created + cannonical induction variable. + + * graphite.h (debug_rename_map): Declared. Fix some comments. + + * graphite.c: Reimplement the code generation from graphite to gimple. + Include value-prof.h. + (loop_iv_stack_get_iv): Do not return NULL for constant substitutions. + (get_old_iv_from_ssa_name): Removed. + (graphite_stmt_p): New. + (new_graphite_bb): Test for useful statements before building a + graphite statement for the basic block. + (free_graphite_bb): Do not free GBB_DATA_REFS: this is a bug + in free_data_ref that calls BITMAP_FREE (DR_VOPS (dr)) without + reason. + (recompute_all_dominators, graphite_verify, + nb_reductions_in_loop, graphite_loop_normal_form): New. + (scop_record_loop): Call graphite_loop_normal_form. + (build_scop_loop_nests): Iterate over all the blocks of the + function instead of relying on the incomplete information from + SCOP_BBS. Return the success of the operation. + (find_params_in_bb): Use the data from GBB_DATA_REFS. + (add_bb_domains): Removed. + (build_loop_iteration_domains): Don't call add_bb_domains. + Add the iteration domain only to the basic blocks that have been + translated to graphite. + (build_scop_conditions_1): Add constraints only if the basic + block have been translated to graphite. + (build_scop_data_accesses): Completely disabled until data + dependence is correctly implemented. + (debug_rename_elt, debug_rename_map_1, debug_rename_map): New. + (remove_all_edges_1, remove_all_edges): Removed. + (get_new_name_from_old_name): New. + (graphite_rename_variables_in_stmt): Renamed + rename_variables_in_stmt. Call get_new_name_from_old_name. + Use replace_exp and update_stmt. + (is_old_iv): Renamed is_iv. + (expand_scalar_variables_stmt): Extra parameter for renaming map. + Use replace_exp and update_stmt. + (expand_scalar_variables_expr): Same. Use the map to get the + new names for the renaming of induction variables and for the + renaming of variables after a basic block has been copied. + (expand_scalar_variables): Same. + (graphite_rename_variables): Renamed rename_variables. + (move_phi_nodes): Removed. + (get_false_edge_from_guard_bb): New. + (build_iv_mapping): Do not insert the induction variable of a + loop in the renaming iv map if the basic block does not belong + to that loop. + (register_old_new_names, graphite_copy_stmts_from_block, + copy_bb_and_scalar_dependences): New. + (translate_clast): Heavily reimplemented: copy basic blocks, + do not move them. Finally, in call cleanup_tree_cfg in gloog. + At each translation step call graphite_verify ensuring the + consistency of the SSA, loops and dominators information. + (collect_virtual_phis, find_vdef_for_var_in_bb, + find_vdef_for_var_1, find_vdef_for_var, + patch_phis_for_virtual_defs): Removed huge hack. + (mark_old_loops, remove_dead_loops, skip_phi_defs, + collect_scop_exit_phi_args, patch_scop_exit_phi_args, + gbb_can_be_ignored, scop_remove_ignoreable_gbbs, ): Removed. + (remove_sese_region, ifsese, if_region_entry, if_region_exit, + if_region_get_condition_block, if_region_set_false_region, + create_if_region_on_edge, move_sese_in_condition, bb_in_sese_p, + sese_find_uses_to_rename_use, sese_find_uses_to_rename_bb, + sese_add_exit_phis_edge, sese_add_exit_phis_var, + rewrite_into_sese_closed_ssa): New. + (gloog): Remove dead code. Early return if code cannot be + generated. Call cleanup_tree_cfg once the scop has been code + generated. + (graphite_trans_scop_block, graphite_trans_loop_block): Do not + block loops with less than two loops. + (graphite_apply_transformations): Remove the call to + scop_remove_ignoreable_gbbs. + (limit_scops): When build_scop_loop_nests fails, continue on next + scop. Fix open_scop.entry. + (graphite_transform_loops): Call recompute_all_dominators: force the + recomputation of correct CDI_DOMINATORS and CDI_POST_DOMINATORS. + Call initialize_original_copy_tables and free_original_copy_tables + to be able to copy basic blocks during code generation. + When build_scop_loop_nests fails, continue on next scop. + (value_clast): New union. + (clast_to_gcc_expression): Fix type cast warning. + +2008-12-10 Richard Guenther + + PR tree-optimization/36792 + * tree-ssa-pre.c (compute_avail): Handle tcc_comparison like + tcc_binary. + +2008-12-10 Daniel Berlin + + PR tree-optimization/36792 + * tree-ssa-pre.c (compute_avail): Don't insert defs into maximal set. + +2008-12-10 Alexandre Oliva + + PR target/37033 + * dwarf2out.c (saved_do_cfi_asm): New. + (dwarf2out_do_frame): Take it into account. + (dwarf2out_d_cfi_asm): Likewise. Set it when appropriate. + +2008-12-10 Alexandre Oliva + + PR middle-end/38271 + * tree-sra.c (sra_build_bf_assignment): Avoid warnings for + variables initialized from SRAed bit fields. + +2008-12-10 Martin Guy + + PR target/37668 + * arm.c (arm_size_rtx_costs, case NEG): Don't fall through if the + result will be in an FPU register. + +2008-12-10 Eric Botcazou + + PR target/37170 + PR target/38448 + * final.c (output_addr_const) : Call assemble_external + on the associated SYMBOL_REF_DECL node, if any. + +2008-12-09 David Daney + + * config/mips/sync.md (sync__12): Replace + MIPS_SYNC_OP_12_NOT_NOP with MIPS_SYNC_OP_12_AND. + (sync_old__12): Remove third paramater to + MIPS_SYNC_OLD_OP_12 macro, replace MIPS_SYNC_OLD_OP_12_NOT_NOP + with MIPS_SYNC_OLD_OP_12_AND. + (sync_new__12): Replace MIPS_SYNC_NEW_OP_12_NOT_NOP + with MIPS_SYNC_NEW_OP_12_AND. + (sync_nand_12): Replace MIPS_SYNC_OP_12_NOT_NOT with + MIPS_SYNC_OP_12_XOR, reduce length attribute to 40. + (sync_old_nand_12): Remove third paramater to MIPS_SYNC_OLD_OP_12 + macro, replace MIPS_SYNC_OLD_OP_12_NOT_NOT with + MIPS_SYNC_OLD_OP_12_XOR and reduce length attribute to 40. + (sync_new_nand_12): Replace MIPS_SYNC_NEW_OP_12_NOT_NOT with + MIPS_SYNC_NEW_OP_12_XOR. + * config/mips/mips.h (MIPS_SYNC_OP_12, MIPS_SYNC_OP_12_NOT_NOP, + MIPS_SYNC_OP_12_NOT_NOT,MIPS_SYNC_OLD_OP_12_NOT_NOP, + MIPS_SYNC_OLD_OP_12_NOT_NOT, MIPS_SYNC_NEW_OP_12, + MIPS_SYNC_NEW_OP_12_NOT_NOP, MIPS_SYNC_NEW_OP_12_NOT_NOT, + MIPS_SYNC_NAND, MIPS_SYNC_OLD_NAND, MIPS_SYNC_NEW_NAND): Rewritten + to implement new __sync_nand semantics. + (MIPS_SYNC_OLD_OP_12): Implement new __sync_nand semantics, and + remove third parameter. + (MIPS_SYNC_OLD_OP_12_NOT_NOP_REG, + MIPS_SYNC_OLD_OP_12_NOT_NOT_REG): Removed. + (MIPS_SYNC_OP_12_NOT_NOP): Renamed to MIPS_SYNC_OP_12_AND. + (MIPS_SYNC_OP_12_NOT_NOT): Renamed to MIPS_SYNC_OP_12_XOR. + (MIPS_SYNC_OLD_OP_12_NOT_NOP): Renamed to MIPS_SYNC_OLD_OP_12_AND. + (MIPS_SYNC_OLD_OP_12_NOT_NOT): Renamed to MIPS_SYNC_OLD_OP_12_XOR. + (MIPS_SYNC_NEW_OP_12_NOT_NOP): Renamed to MIPS_SYNC_NEW_OP_12_AND. + (MIPS_SYNC_NEW_OP_12_NOT_NOT): Renamed to MIPS_SYNC_NEW_OP_12_XOR + +2008-12-09 Tobias Grosser + + * graphite.c (graphite_transform_loops): Always call find_transform () + in ENABLE_CHECKING. So we test these code paths, even if we do not + generate code. + +2008-12-09 Tobias Grosser + + * graphite.c (print_graphite_bb): Fix printing to file != dump_file. + +2008-12-09 Jakub Jelinek + + PR middle-end/38454 + * function.h (struct function): Add always_inline_functions_inlined. + * ipa-inline.c (cgraph_early_inlining): Set it to true. + * tree-optimize.c (execute_fixup_cfg): Likewise. + * builtins.c (avoid_folding_inline_builtin): New function. + (fold_call_expr): Don't optimize always_inline builtins before + inlining. + (fold_call_stmt): Likewise. + (fold_builtin_call_array): Likewise. Don't call + fold_builtin_varargs for BUILT_IN_MD builtins. + + PR tree-optimization/37416 + * tree-scalar-evolution.c (follow_ssa_edge_in_rhs): Handle NOP_EXPR. + +2008-12-09 Janis Johnson + + * doc/sourcebuild.texi (Test Directives): Fix formatting. + +2008-12-09 Vladimir Makarov + + * doc/tm.texi (TARGET_IRA_COVER_CLASSES): Modify description. + + * doc/invoke.texi (-fira-region): Describe new option. + (-fira-algorithm): Change the values. + + * ira-conflicts.c (build_conflict_bit_table, + build_allocno_conflicts): Use ira_reg_classes_intersect_p. + (ira_build_conflicts): Use flag flag_ira_region instead of + flag_ira_algorithm. Prohibit usage of callee-saved likely spilled + base registers for allocnos crossing calls. + + * flags.h (enum ira_algorithm): Redefine. + (enum ira_region): New. + (flag_ira_region): New. + + * cfgloopanal.c (estimate_reg_pressure_cost): Use flag_ira_region + instead of flag_ira_algorithm. + + * toplev.c (flag_ira_algorithm): Change the initial value. + (flag_ira_region): New. + + * ira-int.h (ira_reg_classes_intersect_p, + ira_reg_class_super_classes): New. + + * ira-color.c (update_copy_costs): Use + ira_reg_classes_intersect_p. Use right class to find hard reg + index. + (update_conflict_hard_regno_costs): Ditto. Add a new parameter. + (assign_hard_reg): Ditto. Pass additional argument to + update_conflict_hard_regno_costs. Do not uncoalesce for priority + coloring. + (allocno_priorities, setup_allocno_priorities, + allocno_priority_compare_func): Move before color_allocnos. + (color_allocnos): Add priority coloring. Use flag flag_ira_region + instead of flag_ira_algorithm. + (move_spill_restore): Check classes of the same reg allocno from + different regions. + (update_curr_costs): Use ira_reg_classes_intersect_p. + (ira_reassign_conflict_allocnos): Ditto. + + * opts.c (decode_options): Always set up flag_ira. Set up + flag_ira_algorithm. Warn CB can not be used for architecture. + (common_handle_option): Modify code for -fira-algorithm. Add code + to process -fira-region. + + * ira-lives.c (update_allocno_pressure_excess_length): Process + superclasses too. + (set_allocno_live, clear_allocno_live, mark_reg_live, + mark_reg_dead, process_bb_node_lives): Ditto. + + * ira-emit.c (ira_emit): Fix insn codes. + + * ira-build.c (propagate_allocno_info): Use flag flag_ira_region + instead of flag_ira_algorithm. + (allocno_range_compare_func): Ignore classes for priority + coloring. + (setup_min_max_conflict_allocno_ids): Ditto. + (ira_flattening): Use ira_reg_classes_intersect_p. + + * genpreds.c (write_enum_constraint_num): Output + CONSTRAINT__LIMIT. + + * common.opt (fira-algorithm): Modify. + (fira-region): New. + + * ira.c (setup_class_hard_regs): Initialize. + (setup_cover_and_important_classes): Modify code setting class + related info for priority coloring. + (setup_class_translate): Ditto. + (ira_reg_classes_intersect_p, ira_reg_class_super_classes): New. + (setup_reg_class_intersect_union): Rename to + setup_reg_class_relations. Add code for setting up new variables. + (find_reg_class_closure): Do not check targetm.ira_cover_classes. + (ira): Use flag flag_ira_region instead of flag_ira_algorithm. + + * ira-costs.c (common_classes): New. + (print_costs): Use flag flag_ira_region instead of + flag_ira_algorithm. + (find_allocno_class_costs): Ditto. Use common_classes. Translate + alt_class. + (ira_costs): Allocate/deallocate common_classes. + + * config/m32c/m32.h (REG_ALLOC_ORDER): Add reg 19. + (REG_CLASS_CONTENTS, reg_class, REG_CLASS_NAMES): New entries for + R02A_REGS. + + * reload1.c (choose_reload_regs): Use MODE_INT for partial ints in + smallest_mode_for_size. + +2008-12-10 Ben Elliston + + * config/rs6000/linux-unwind.h (get_regs): Constify casts. + +2008-12-09 Jan Hubicka + + * predict.c (estimate_bb_frequencies): Fix test if profile is present. + +2008-12-09 Jakub Jelinek + + PR tree-optimization/35468 + * tree-ssa-ccp.c (fold_stmt_r): Don't fold reads from constant + string on LHS. + +2008-12-09 Richard Guenther + + PR tree-optimization/38445 + * tree-ssa-structalias.c (emit_pointer_definition): Only visit + names once. + (emit_alias_warning): Adjust. + +2008-12-09 Andrew Haley + + * fixed-value.c (do_fixed_add): Add comment. + * tree-ssa-loop-ivopts.c (iv_ca_cost): Likewise. + * builtins.c (fold_builtin_sqrt): Likewise. + +2008-12-09 Kai Tietz + + PR/38366 + * function.c (aggregate_value_p): Get fntype from CALL_EXPR in any + case. + * calls.c (nitialize_argument_information): Add fntype argument + and use it for calls.promote_function_args. + (expand_call): Pass fntype to aggregate_value_p if no fndecl + available and pass additional fntype to + initialize_argument_information. + * config/i386/i386.c (ix86_reg_parm_stack_space): Remove cfun part + to get function abi type. + (init_cumulative_args): Use for abi kind detection fntype, when no + fndecl is available. + +2008-12-09 Andreas Krebbel + + * config/s390/s390.md (movti, movdi_64, movdi_31, + *movsi_zarch, *movhi, *movqi, *mov_64, *mov_31, + *mov_64dfp, *mov_64, *mov_31, mov): Remove + Q->Q alternative. + (Integer->BLKmode splitter): Removed. + +2008-12-08 Uros Bizjak + + * config/alpha/alpha.c (alpha_set_memflags): Process memory + references in full insn sequence. + +2008-12-09 Jason Merrill + + * gimplify.c (gimplify_init_constructor): Revert to using < rather + than <= for sparseness test. + + PR c++/38410 + * gimplify.c (gimplify_init_constructor): Don't write out a static + copy of the CONSTRUCTOR for TREE_ADDRESSABLE types or small sparse + initializers. + +2008-12-09 Tobias Grosser + + PR middle-end/38084 + Fix testsuite/gfortran.dg/graphite/id-3.f90. + * graphite.c (scopdet_basic_block_info): Fix bug that found some + regions more than once. + +2008-12-09 Ben Elliston + + * emutls.c (__emutls_get_address): Prototype. + (__emutls_register_common): Likewise. + + * config/dfp-bit.c (DFP_TO_INT): Remove unnecessary cast. + +2008-12-09 Ben Elliston + + * config/rs6000/darwin-ldouble.c (fmsub): Remove unused variable, v. + +2008-12-08 Steve Ellcey + + * config/ia64/ia64.md (UNSPECV_GOTO_RECEIVER): New constant. + (nonlocal_goto_receiver): New instruction. + +2008-12-08 Jakub Jelinek + + PR c/35443 + * c-pretty-print.c (pp_c_expression): Handle BIND_EXPR. + + PR c/35442 + * c-pretty-print.c (pp_c_cast_expression, pp_c_expression): Handle + VIEW_CONVERT_EXPR the same as CASE_CONVERT. + +2008-12-08 Richard Henderson + + PR 38240 + * tree.h (TYPE_MODE): Invoke vector_type_mode when needed. + (SET_TYPE_MODE): New. + * c-decl.c (parser_xref_tag): Use it. + (finish_enum): Likewise. + * tree.c (build_pointer_type_for_mode): Likewise. + (build_reference_type_for_mode, build_index_type): Likewise. + (build_range_type, make_vector_type): Likewise. + (build_common_tree_nodes_2): Likewise. + * stor-layout.c (compute_record_mode): Likewise. + (finalize_type_size, layout_type, make_fract_type): Likewise. + (make_accum_type, initialize_sizetypes): Likewise. + (vector_type_mode): New. + * function.c (allocate_struct_function): Call + invoke_set_current_function_hook before querying anything else. + + * config/i386/i386.c (ix86_valid_target_attribute_inner_p): Add avx. + +2008-12-08 Luis Machado + + * alias.c (find_base_term): Synch LO_SUM handling with what + find_base_value does. + +2008-12-08 Andrew Haley + Kamaraju Kusumanchi + + * gimple.h (gimple_build_try): Fix declaration. + + * builtins.c (fold_builtin_sqrt): Don't use a conditional operator. + * fixed-value.c (do_fixed_add): Likewise. + * tree-ssa-loop-ivopts.c (iv_ca_cost): Likewise. + +2008-12-08 Jakub Jelinek + + PR middle-end/36802 + * omp-low.c (use_pointer_for_field): Only call maybe_lookup_decl + on parallel and task contexts. + +2008-12-07 Eric Botcazou + + * gimple.c (recalculate_side_effects) : New case. + +2008-12-07 Richard Guenther + + PR tree-optimization/38405 + * tree-vrp.c (simplify_truth_ops_using_ranges): Make sure to + not sign-extend truth values. + +2008-12-07 Eric Botcazou + + * tree-sra.c (scalarize_use): Create another temporary with the proper + type for signed types in the use_all && !is_output bitfield case. + 2008-12-06 Steven Bosscher PR rtl-optimization/36365 diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index b2d83e62a8..6a9c2327c9 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20081207 +20081212 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 097159c645..644694b6ad 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -183,8 +183,6 @@ dfp.o-warn = -Wno-error bitmap.o-warn = -Wno-error # dominance.c contains a -Wc++compat warning. dominance.o-warn = -Wno-error -# graphite.c contains code calling cloog that has problems. -graphite.o-warn = -Wno-error # mips-tfile.c contains -Wcast-qual warnings. mips-tfile.o-warn = -Wno-error @@ -2368,7 +2366,8 @@ tree-data-ref.o: tree-data-ref.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ graphite.o: graphite.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(GGC_H) $(TREE_H) $(RTL_H) $(BASIC_BLOCK_H) $(DIAGNOSTIC_H) $(TOPLEV_H) \ $(TREE_FLOW_H) $(TREE_DUMP_H) $(TIMEVAR_H) $(CFGLOOP_H) $(GIMPLE_H) domwalk.h \ - $(TREE_DATA_REF_H) $(SCEV_H) tree-pass.h tree-chrec.h graphite.h pointer-set.h + $(TREE_DATA_REF_H) $(SCEV_H) tree-pass.h tree-chrec.h graphite.h pointer-set.h \ + value-prof.h tree-vect-analyze.o: tree-vect-analyze.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ $(TM_H) $(GGC_H) $(OPTABS_H) $(TREE_H) $(RECOG_H) $(BASIC_BLOCK_H) \ $(DIAGNOSTIC_H) $(TREE_FLOW_H) $(TREE_DUMP_H) $(TIMEVAR_H) $(CFGLOOP_H) \ diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index b2425ba92f..166baa82dc 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2008-12-09 Jakub Jelinek + + PR ada/38450 + * gcc-interface/utils.c (finish_record_type): Use SET_TYPE_MODE. + * gcc-interface/decl.c (gnat_to_gnu_entity, make_aligning_type): + Likewise. + 2008-12-05 Sebastian Pop PR bootstrap/38262 diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c index 14fcd634b6..20c5fb4686 100644 --- a/gcc/ada/gcc-interface/decl.c +++ b/gcc/ada/gcc-interface/decl.c @@ -2032,7 +2032,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) corresponding fat pointer. */ TREE_TYPE (gnu_type) = TYPE_POINTER_TO (gnu_type) = TYPE_REFERENCE_TO (gnu_type) = gnu_fat_type; - TYPE_MODE (gnu_type) = BLKmode; + SET_TYPE_MODE (gnu_type, BLKmode); TYPE_ALIGN (gnu_type) = TYPE_ALIGN (tem); SET_TYPE_UNCONSTRAINED_ARRAY (gnu_fat_type, gnu_type); @@ -2873,7 +2873,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) that these objects will always be placed in memory. Do the same thing for limited record types. */ if (Is_Tagged_Type (gnat_entity) || Is_Limited_Record (gnat_entity)) - TYPE_MODE (gnu_type) = BLKmode; + SET_TYPE_MODE (gnu_type, BLKmode); /* If this is a derived type, we must make the alias set of this type the same as that of the type we are derived from. We assume here @@ -5572,7 +5572,7 @@ make_aligning_type (tree type, unsigned int align, tree size, = size_binop (PLUS_EXPR, size, size_int (room + align / BITS_PER_UNIT)); - TYPE_MODE (record_type) = BLKmode; + SET_TYPE_MODE (record_type, BLKmode); copy_alias_set (record_type, type); return record_type; @@ -5721,8 +5721,8 @@ make_packable_type (tree type, bool in_record) /* Try harder to get a packable type if necessary, for example in case the record itself contains a BLKmode field. */ if (in_record && TYPE_MODE (new_type) == BLKmode) - TYPE_MODE (new_type) - = mode_for_size_tree (TYPE_SIZE (new_type), MODE_INT, 1); + SET_TYPE_MODE (new_type, + mode_for_size_tree (TYPE_SIZE (new_type), MODE_INT, 1)); /* If neither the mode nor the size has shrunk, return the old type. */ if (TYPE_MODE (new_type) == BLKmode && new_size >= size) diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c index 131b2376ac..7b52d90224 100644 --- a/gcc/ada/gcc-interface/utils.c +++ b/gcc/ada/gcc-interface/utils.c @@ -839,7 +839,7 @@ finish_record_type (tree record_type, tree fieldlist, int rep_level, if (rep_level > 0) { TYPE_ALIGN (record_type) = MAX (BITS_PER_UNIT, TYPE_ALIGN (record_type)); - TYPE_MODE (record_type) = BLKmode; + SET_TYPE_MODE (record_type, BLKmode); if (!had_size_unit) TYPE_SIZE_UNIT (record_type) = size_zero_node; diff --git a/gcc/alias.c b/gcc/alias.c index 4cadb6b2a2..e5133d6a8c 100644 --- a/gcc/alias.c +++ b/gcc/alias.c @@ -1408,6 +1408,9 @@ find_base_term (rtx x) return 0; /* Fall through. */ case LO_SUM: + /* The standard form is (lo_sum reg sym) so look only at the + second operand. */ + return find_base_term (XEXP (x, 1)); case PLUS: case MINUS: { diff --git a/gcc/builtins.c b/gcc/builtins.c index 4d507cf867..afb3b3fdb3 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -7681,8 +7681,13 @@ fold_builtin_sqrt (tree arg, tree type) tree arg0 = CALL_EXPR_ARG (arg, 0); tree tree_root; /* The inner root was either sqrt or cbrt. */ - REAL_VALUE_TYPE dconstroot = - BUILTIN_SQRT_P (fcode) ? dconsthalf : dconst_third (); + /* This was a conditional expression but it triggered a bug + in the Solaris 8 compiler. */ + REAL_VALUE_TYPE dconstroot; + if (BUILTIN_SQRT_P (fcode)) + dconstroot = dconsthalf; + else + dconstroot = dconst_third (); /* Adjust for the outer root. */ SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1); @@ -10792,6 +10797,22 @@ fold_builtin_varargs (tree fndecl, tree exp, bool ignore ATTRIBUTE_UNUSED) return NULL_TREE; } +/* Return true if FNDECL shouldn't be folded right now. + If a built-in function has an inline attribute always_inline + wrapper, defer folding it after always_inline functions have + been inlined, otherwise e.g. -D_FORTIFY_SOURCE checking + might not be performed. */ + +static bool +avoid_folding_inline_builtin (tree fndecl) +{ + return (DECL_DECLARED_INLINE_P (fndecl) + && DECL_DISREGARD_INLINE_LIMITS (fndecl) + && cfun + && !cfun->always_inline_functions_inlined + && lookup_attribute ("always_inline", DECL_ATTRIBUTES (fndecl))); +} + /* A wrapper function for builtin folding that prevents warnings for "statement without effect" and the like, caused by removing the call node earlier than the warning is generated. */ @@ -10824,6 +10845,9 @@ fold_call_expr (tree exp, bool ignore) return NULL_TREE; } + if (avoid_folding_inline_builtin (fndecl)) + return NULL_TREE; + /* FIXME: Don't use a list in this interface. */ if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD) return targetm.fold_builtin (fndecl, CALL_EXPR_ARGS (exp), ignore); @@ -10926,6 +10950,8 @@ fold_builtin_call_array (tree type, && DECL_FUNCTION_CODE (fndecl2) == BUILT_IN_VA_ARG_PACK) return build_call_array (type, fn, n, argarray); } + if (avoid_folding_inline_builtin (fndecl)) + return build_call_array (type, fn, n, argarray); if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD) { tree arglist = NULL_TREE; @@ -10934,6 +10960,7 @@ fold_builtin_call_array (tree type, ret = targetm.fold_builtin (fndecl, arglist, false); if (ret) return ret; + return build_call_array (type, fn, n, argarray); } else if (n <= MAX_ARGS_TO_FOLD_BUILTIN) { @@ -13642,6 +13669,8 @@ fold_call_stmt (gimple stmt, bool ignore) { int nargs = gimple_call_num_args (stmt); + if (avoid_folding_inline_builtin (fndecl)) + return NULL_TREE; /* FIXME: Don't use a list in this interface. */ if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD) { diff --git a/gcc/c-decl.c b/gcc/c-decl.c index 6f88f62604..7f7f2b00ac 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -5302,7 +5302,7 @@ parser_xref_tag (enum tree_code code, tree name) { /* Give the type a default layout like unsigned int to avoid crashing if it does not get defined. */ - TYPE_MODE (ref) = TYPE_MODE (unsigned_type_node); + SET_TYPE_MODE (ref, TYPE_MODE (unsigned_type_node)); TYPE_ALIGN (ref) = TYPE_ALIGN (unsigned_type_node); TYPE_USER_ALIGN (ref) = 0; TYPE_UNSIGNED (ref) = 1; @@ -5952,7 +5952,7 @@ finish_enum (tree enumtype, tree values, tree attributes) TYPE_MAX_VALUE (tem) = TYPE_MAX_VALUE (enumtype); TYPE_SIZE (tem) = TYPE_SIZE (enumtype); TYPE_SIZE_UNIT (tem) = TYPE_SIZE_UNIT (enumtype); - TYPE_MODE (tem) = TYPE_MODE (enumtype); + SET_TYPE_MODE (tem, TYPE_MODE (enumtype)); TYPE_PRECISION (tem) = TYPE_PRECISION (enumtype); TYPE_ALIGN (tem) = TYPE_ALIGN (enumtype); TYPE_USER_ALIGN (tem) = TYPE_USER_ALIGN (enumtype); diff --git a/gcc/c-pretty-print.c b/gcc/c-pretty-print.c index cf1c6c3f52..8676205052 100644 --- a/gcc/c-pretty-print.c +++ b/gcc/c-pretty-print.c @@ -1629,6 +1629,7 @@ pp_c_cast_expression (c_pretty_printer *pp, tree e) case FLOAT_EXPR: case FIX_TRUNC_EXPR: CASE_CONVERT: + case VIEW_CONVERT_EXPR: pp_c_type_cast (pp, TREE_TYPE (e)); pp_c_cast_expression (pp, TREE_OPERAND (e, 0)); break; @@ -2020,6 +2021,7 @@ pp_c_expression (c_pretty_printer *pp, tree e) case FLOAT_EXPR: case FIX_TRUNC_EXPR: CASE_CONVERT: + case VIEW_CONVERT_EXPR: pp_c_cast_expression (pp, e); break; @@ -2101,6 +2103,12 @@ pp_c_expression (c_pretty_printer *pp, tree e) pp_postfix_expression (pp, TREE_OPERAND (e, 1)); break; + case BIND_EXPR: + /* We don't yet have a way of dumping statements in a + human-readable format. */ + pp_string (pp, "({...})"); + break; + default: pp_unsupported_tree (pp, e); break; diff --git a/gcc/calls.c b/gcc/calls.c index e2c4fcb8a6..03994d4ecf 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -136,7 +136,7 @@ static int compute_argument_block_size (int, struct args_size *, tree, tree, int static void initialize_argument_information (int, struct arg_data *, struct args_size *, int, tree, tree, - tree, CUMULATIVE_ARGS *, int, + tree, tree, CUMULATIVE_ARGS *, int, rtx *, int *, int *, int *, bool *, bool); static void compute_argument_addresses (struct arg_data *, rtx, int); @@ -938,7 +938,7 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED, struct args_size *args_size, int n_named_args ATTRIBUTE_UNUSED, tree exp, tree struct_value_addr_value, - tree fndecl, + tree fndecl, tree fntype, CUMULATIVE_ARGS *args_so_far, int reg_parm_stack_space, rtx *old_stack_level, int *old_pending_adj, @@ -1119,7 +1119,9 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED, mode = TYPE_MODE (type); unsignedp = TYPE_UNSIGNED (type); - if (targetm.calls.promote_function_args (fndecl ? TREE_TYPE (fndecl) : 0)) + if (targetm.calls.promote_function_args (fndecl + ? TREE_TYPE (fndecl) + : fntype)) mode = promote_mode (type, mode, &unsignedp, 1); args[i].unsignedp = unsignedp; @@ -2088,7 +2090,7 @@ expand_call (tree exp, rtx target, int ignore) /* Set up a place to return a structure. */ /* Cater to broken compilers. */ - if (aggregate_value_p (exp, fndecl)) + if (aggregate_value_p (exp, (!fndecl ? fntype : fndecl))) { /* This call returns a big structure. */ flags &= ~(ECF_CONST | ECF_PURE | ECF_LOOPING_CONST_OR_PURE); @@ -2245,7 +2247,7 @@ expand_call (tree exp, rtx target, int ignore) arguments into ARGS_SIZE, etc. */ initialize_argument_information (num_actuals, args, &args_size, n_named_args, exp, - structure_value_addr_value, fndecl, + structure_value_addr_value, fndecl, fntype, &args_so_far, reg_parm_stack_space, &old_stack_level, &old_pending_adj, &must_preallocate, &flags, diff --git a/gcc/cfgloopanal.c b/gcc/cfgloopanal.c index d59fa2fb50..88c5e95626 100644 --- a/gcc/cfgloopanal.c +++ b/gcc/cfgloopanal.c @@ -396,8 +396,8 @@ estimate_reg_pressure_cost (unsigned n_new, unsigned n_old, bool speed) one. */ cost = target_spill_cost [speed] * n_new; - if (optimize && flag_ira && (flag_ira_algorithm == IRA_ALGORITHM_REGIONAL - || flag_ira_algorithm == IRA_ALGORITHM_MIXED) + if (optimize && flag_ira && (flag_ira_region == IRA_REGION_ALL + || flag_ira_region == IRA_REGION_MIXED) && number_of_loops () <= (unsigned) IRA_MAX_LOOPS_NUM) /* IRA regional allocation deals with high register pressure better. So decrease the cost (to do more accurate the cost diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c index a7dc507686..0e1bb0a3d9 100644 --- a/gcc/cfgrtl.c +++ b/gcc/cfgrtl.c @@ -1731,7 +1731,8 @@ rtl_verify_flow_info_1 (void) } FOR_BB_INSNS (bb, insn) - if (BLOCK_FOR_INSN (insn) != bb) + if (!BARRIER_P (insn) + && BLOCK_FOR_INSN (insn) != bb) { error ("insn %d basic block pointer is %d, should be %d", INSN_UID (insn), diff --git a/gcc/common.opt b/gcc/common.opt index 4e680676c5..4ffe1fd051 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -683,7 +683,11 @@ Use integrated register allocator. fira-algorithm= Common Joined RejectNegative --fira-algorithm=[regional|CB|mixed] Set the used IRA algorithm +-fira-algorithm=[CB|priority] Set the used IRA algorithm + +fira-region= +Common Joined RejectNegative +-fira-region=[one|all|mixed] Set regions for IRA fira-coalesce Common Report Var(flag_ira_coalesce) Init(0) diff --git a/gcc/config.gcc b/gcc/config.gcc index 5e9e89d980..ba44a95188 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -298,7 +298,8 @@ i[34567]86-*-*) extra_headers="cpuid.h mmintrin.h mm3dnow.h xmmintrin.h emmintrin.h pmmintrin.h tmmintrin.h ammintrin.h smmintrin.h nmmintrin.h bmmintrin.h mmintrin-common.h - wmmintrin.h immintrin.h avxintrin.h cross-stdarg.h" + wmmintrin.h immintrin.h x86intrin.h avxintrin.h + cross-stdarg.h" ;; x86_64-*-*) cpu_type=i386 @@ -307,7 +308,8 @@ x86_64-*-*) extra_headers="cpuid.h mmintrin.h mm3dnow.h xmmintrin.h emmintrin.h pmmintrin.h tmmintrin.h ammintrin.h smmintrin.h nmmintrin.h bmmintrin.h mmintrin-common.h - wmmintrin.h immintrin.h avxintrin.h cross-stdarg.h" + wmmintrin.h immintrin.h x86intrin.h avxintrin.h + cross-stdarg.h" need_64bit_hwint=yes ;; ia64-*-*) diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index 26feea52dd..52ae122f6e 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -1603,18 +1603,17 @@ alpha_set_memflags_1 (rtx *xp, void *data) return -1; } -/* Given INSN, which is an INSN list or the PATTERN of a single insn - generated to perform a memory operation, look for any MEMs in either +/* Given SEQ, which is an INSN list, look for any MEMs in either a SET_DEST or a SET_SRC and copy the in-struct, unchanging, and volatile flags from REF into each of the MEMs found. If REF is not a MEM, don't do anything. */ void -alpha_set_memflags (rtx insn, rtx ref) +alpha_set_memflags (rtx seq, rtx ref) { - rtx *base_ptr; + rtx insn; - if (GET_CODE (ref) != MEM) + if (!MEM_P (ref)) return; /* This is only called from alpha.md, after having had something @@ -1627,11 +1626,11 @@ alpha_set_memflags (rtx insn, rtx ref) && !MEM_READONLY_P (ref)) return; - if (INSN_P (insn)) - base_ptr = &PATTERN (insn); - else - base_ptr = &insn; - for_each_rtx (base_ptr, alpha_set_memflags_1, (void *) ref); + for (insn = seq; insn; insn = NEXT_INSN (insn)) + if (INSN_P (insn)) + for_each_rtx (&PATTERN (insn), alpha_set_memflags_1, (void *) ref); + else + gcc_unreachable (); } static rtx alpha_emit_set_const (rtx, enum machine_mode, HOST_WIDE_INT, diff --git a/gcc/config/alpha/sync.md b/gcc/config/alpha/sync.md index fe8301f344..1c7ee45c58 100644 --- a/gcc/config/alpha/sync.md +++ b/gcc/config/alpha/sync.md @@ -28,17 +28,17 @@ (define_expand "memory_barrier" - [(set (mem:BLK (match_dup 0)) - (unspec:BLK [(mem:BLK (match_dup 0))] UNSPEC_MB))] + [(set (match_dup 0) + (unspec:BLK [(match_dup 0)] UNSPEC_MB))] "" { - operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (DImode)); + operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode)); MEM_VOLATILE_P (operands[0]) = 1; }) (define_insn "*mb_internal" [(set (match_operand:BLK 0 "" "") - (unspec:BLK [(match_operand:BLK 1 "" "")] UNSPEC_MB))] + (unspec:BLK [(match_dup 0)] UNSPEC_MB))] "" "mb" [(set_attr "type" "mb")]) diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index a1cef0bd10..497564a227 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -5281,7 +5281,11 @@ arm_size_rtx_costs (rtx x, int code, int outer_code, int *total) case NEG: if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT) - *total = COSTS_N_INSNS (1); + { + *total = COSTS_N_INSNS (1); + return false; + } + /* Fall through */ case NOT: *total = COSTS_N_INSNS (ARM_NUM_REGS (mode)); diff --git a/gcc/config/dfp-bit.c b/gcc/config/dfp-bit.c index bfce851d7b..8437491a75 100644 --- a/gcc/config/dfp-bit.c +++ b/gcc/config/dfp-bit.c @@ -536,7 +536,7 @@ DFP_TO_INT (DFP_C_TYPE x) /* Rescale if the exponent is less than zero. */ decNumberToIntegralValue (&n2, &n1, &context); /* Get a value to use for the quantize call. */ - decNumberFromString (&qval, (char *) "1.", &context); + decNumberFromString (&qval, "1.", &context); /* Force the exponent to zero. */ decNumberQuantize (&n1, &n2, &qval, &context); /* Get a string, which at this point will not include an exponent. */ diff --git a/gcc/config/fp-bit.c b/gcc/config/fp-bit.c index bdf04ffd31..1da69b2cb7 100644 --- a/gcc/config/fp-bit.c +++ b/gcc/config/fp-bit.c @@ -140,7 +140,7 @@ extern const fp_number_type __thenan_df; INLINE static fp_number_type * -nan (void) +makenan (void) { /* Discard the const qualifier... */ #ifdef TFLOAT @@ -621,7 +621,7 @@ _fpadd_parts (fp_number_type * a, { /* Adding infinities with opposite signs yields a NaN. */ if (isinf (b) && a->sign != b->sign) - return nan (); + return makenan (); return a; } if (isinf (b)) @@ -802,7 +802,7 @@ _fpmul_parts ( fp_number_type * a, if (isinf (a)) { if (iszero (b)) - return nan (); + return makenan (); a->sign = a->sign != b->sign; return a; } @@ -810,7 +810,7 @@ _fpmul_parts ( fp_number_type * a, { if (iszero (a)) { - return nan (); + return makenan (); } b->sign = a->sign != b->sign; return b; @@ -988,7 +988,7 @@ _fpdiv_parts (fp_number_type * a, if (isinf (a) || iszero (a)) { if (a->class == b->class) - return nan (); + return makenan (); return a; } diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index f83ed7e14b..12e9e5abfe 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -3408,6 +3408,7 @@ ix86_valid_target_attribute_inner_p (tree args, char *p_strings[]) IX86_ATTR_ISA ("3dnow", OPT_m3dnow), IX86_ATTR_ISA ("abm", OPT_mabm), IX86_ATTR_ISA ("aes", OPT_maes), + IX86_ATTR_ISA ("avx", OPT_mavx), IX86_ATTR_ISA ("mmx", OPT_mmmx), IX86_ATTR_ISA ("pclmul", OPT_mpclmul), IX86_ATTR_ISA ("popcnt", OPT_mpopcnt), @@ -4548,16 +4549,12 @@ ix86_must_pass_in_stack (enum machine_mode mode, const_tree type) int ix86_reg_parm_stack_space (const_tree fndecl) { - int call_abi = 0; - /* For libcalls it is possible that there is no fndecl at hand. - Therefore assume for this case the default abi of the target. */ - if (!fndecl) - call_abi = (cfun ? cfun->machine->call_abi : DEFAULT_ABI); - else if (TREE_CODE (fndecl) == FUNCTION_DECL) + int call_abi = SYSV_ABI; + if (fndecl != NULL_TREE && TREE_CODE (fndecl) == FUNCTION_DECL) call_abi = ix86_function_abi (fndecl); else call_abi = ix86_function_type_abi (fndecl); - if (call_abi == 1) + if (call_abi == MS_ABI) return 32; return 0; } @@ -4646,7 +4643,10 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */ struct cgraph_local_info *i = fndecl ? cgraph_local_info (fndecl) : NULL; memset (cum, 0, sizeof (*cum)); - cum->call_abi = ix86_function_type_abi (fntype); + if (fndecl) + cum->call_abi = ix86_function_abi (fndecl); + else + cum->call_abi = ix86_function_type_abi (fntype); /* Set up the number of registers to use for passing arguments. */ cum->nregs = ix86_regparm; if (TARGET_64BIT) diff --git a/gcc/config/i386/x86intrin.h b/gcc/config/i386/x86intrin.h new file mode 100644 index 0000000000..ab188690f5 --- /dev/null +++ b/gcc/config/i386/x86intrin.h @@ -0,0 +1,73 @@ +/* Copyright (C) 2008 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING. If not, write to + the Free Software Foundation, 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* As a special exception, if you include this header file into source + files compiled by GCC, this header file does not by itself cause + the resulting executable to be covered by the GNU General Public + License. This exception does not however invalidate any other + reasons why the executable file might be covered by the GNU General + Public License. */ + +#ifndef _X86INTRIN_H_INCLUDED +#define _X86INTRIN_H_INCLUDED + +#ifdef __MMX__ +#include +#endif + +#ifdef __SSE__ +#include +#endif + +#ifdef __SSE2__ +#include +#endif + +#ifdef __SSE3__ +#include +#endif + +#ifdef __SSSE3__ +#include +#endif + +#ifdef __SSE4a__ +#include +#endif + +#if defined (__SSE4_2__) || defined (__SSE4_1__) +#include +#endif + +#ifdef __SSE5__ +#include +#endif + +#if defined (__AES__) || defined (__PCLMUL__) +#include +#endif + +/* For including AVX instructions */ +#include + +#ifdef __3dNOW__ +#include +#endif + +#endif /* _X86INTRIN_H_INCLUDED */ diff --git a/gcc/config/ia64/ia64.md b/gcc/config/ia64/ia64.md index b03032dd02..b4894ab8bb 100644 --- a/gcc/config/ia64/ia64.md +++ b/gcc/config/ia64/ia64.md @@ -102,6 +102,7 @@ (UNSPECV_PSAC_ALL 5) ; pred.safe_across_calls (UNSPECV_PSAC_NORMAL 6) (UNSPECV_SETJMP_RECEIVER 7) + (UNSPECV_GOTO_RECEIVER 8) ]) (include "predicates.md") @@ -6400,6 +6401,17 @@ DONE; }) +(define_insn_and_split "nonlocal_goto_receiver" + [(unspec_volatile [(const_int 0)] UNSPECV_GOTO_RECEIVER)] + "" + "#" + "reload_completed" + [(const_int 0)] +{ + ia64_reload_gp (); + DONE; +}) + (define_insn_and_split "builtin_setjmp_receiver" [(unspec_volatile [(match_operand:DI 0 "" "")] UNSPECV_SETJMP_RECEIVER)] "" diff --git a/gcc/config/m32c/m32c.h b/gcc/config/m32c/m32c.h index 2fb636a5a3..2292a33bb5 100644 --- a/gcc/config/m32c/m32c.h +++ b/gcc/config/m32c/m32c.h @@ -224,7 +224,7 @@ machine_function; #define REG_ALLOC_ORDER { \ 0, 1, 2, 3, 4, 5, /* r0..r3, a0, a1 */ \ - 12, 13, 14, 15, 16, 17, 18, /* mem0..mem7 */ \ + 12, 13, 14, 15, 16, 17, 18, 19, /* mem0..mem7 */ \ 6, 7, 8, 9, 10, 11 /* sb, fb, sp, pc, flg, ap */ } /* How Values Fit in Registers */ @@ -270,6 +270,7 @@ machine_function; { 0x000001f0 }, /* PS - a0 a1 sb fp sp */\ { 0x0000000f }, /* SI - r0r2 r1r3 a0a1 */\ { 0x0000003f }, /* HI - r0 r1 r2 r3 a0 a1 */\ + { 0x00000033 }, /* R02A - r0r2 a0 a1 */ \ { 0x0000003f }, /* RA - r0..r3 a0 a1 */\ { 0x0000007f }, /* GENERAL */\ { 0x00000400 }, /* FLG */\ @@ -308,6 +309,7 @@ enum reg_class PS_REGS, SI_REGS, HI_REGS, + R02A_REGS, RA_REGS, GENERAL_REGS, FLG_REGS, @@ -348,6 +350,7 @@ enum reg_class "PS_REGS", \ "SI_REGS", \ "HI_REGS", \ +"R02A_REGS", \ "RA_REGS", \ "GENERAL_REGS", \ "FLG_REGS", \ diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index 6f98cd0290..a6444b5f99 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -3183,24 +3183,25 @@ while (0) - Uses scratch register %4. - NOT_OP are the optional instructions to do a bit-wise not - operation in conjunction with an AND INSN to generate a sync_nand - operation. */ -#define MIPS_SYNC_OP_12(INSN, NOT_OP) \ + AND_OP is an instruction done after INSN to mask INSN's result + with the mask. For most operations, this is an AND with the + inclusive mask (%1). For nand operations -- where the result of + INSN is already correctly masked -- it instead performs a bitwise + not. */ +#define MIPS_SYNC_OP_12(INSN, AND_OP) \ "%(%<%[%|sync\n" \ "1:\tll\t%4,%0\n" \ "\tand\t%@,%4,%2\n" \ - NOT_OP \ "\t" INSN "\t%4,%4,%z3\n" \ - "\tand\t%4,%4,%1\n" \ + AND_OP \ "\tor\t%@,%@,%4\n" \ "\tsc\t%@,%0\n" \ "\tbeq%?\t%@,%.,1b\n" \ "\tnop\n" \ "\tsync%-%]%>%)" -#define MIPS_SYNC_OP_12_NOT_NOP "" -#define MIPS_SYNC_OP_12_NOT_NOT "\tnor\t%4,%4,%.\n" +#define MIPS_SYNC_OP_12_AND "\tand\t%4,%4,%1\n" +#define MIPS_SYNC_OP_12_XOR "\txor\t%4,%4,%1\n" /* Return an asm string that atomically: @@ -3213,29 +3214,25 @@ while (0) - Uses scratch register %5. - NOT_OP are the optional instructions to do a bit-wise not - operation in conjunction with an AND INSN to generate a sync_nand - operation. - - REG is used in conjunction with NOT_OP and is used to select the - register operated on by the INSN. */ -#define MIPS_SYNC_OLD_OP_12(INSN, NOT_OP, REG) \ + AND_OP is an instruction done after INSN to mask INSN's result + with the mask. For most operations, this is an AND with the + inclusive mask (%1). For nand operations -- where the result of + INSN is already correctly masked -- it instead performs a bitwise + not. */ +#define MIPS_SYNC_OLD_OP_12(INSN, AND_OP) \ "%(%<%[%|sync\n" \ "1:\tll\t%0,%1\n" \ "\tand\t%@,%0,%3\n" \ - NOT_OP \ - "\t" INSN "\t%5," REG ",%z4\n" \ - "\tand\t%5,%5,%2\n" \ + "\t" INSN "\t%5,%0,%z4\n" \ + AND_OP \ "\tor\t%@,%@,%5\n" \ "\tsc\t%@,%1\n" \ "\tbeq%?\t%@,%.,1b\n" \ "\tnop\n" \ "\tsync%-%]%>%)" -#define MIPS_SYNC_OLD_OP_12_NOT_NOP "" -#define MIPS_SYNC_OLD_OP_12_NOT_NOP_REG "%0" -#define MIPS_SYNC_OLD_OP_12_NOT_NOT "\tnor\t%5,%0,%.\n" -#define MIPS_SYNC_OLD_OP_12_NOT_NOT_REG "%5" +#define MIPS_SYNC_OLD_OP_12_AND "\tand\t%5,%5,%2\n" +#define MIPS_SYNC_OLD_OP_12_XOR "\txor\t%5,%5,%2\n" /* Return an asm string that atomically: @@ -3246,24 +3243,25 @@ while (0) - Sets %0 to the new value of %1. - NOT_OP are the optional instructions to do a bit-wise not - operation in conjunction with an AND INSN to generate a sync_nand - operation. */ -#define MIPS_SYNC_NEW_OP_12(INSN, NOT_OP) \ + AND_OP is an instruction done after INSN to mask INSN's result + with the mask. For most operations, this is an AND with the + inclusive mask (%1). For nand operations -- where the result of + INSN is already correctly masked -- it instead performs a bitwise + not. */ +#define MIPS_SYNC_NEW_OP_12(INSN, AND_OP) \ "%(%<%[%|sync\n" \ "1:\tll\t%0,%1\n" \ "\tand\t%@,%0,%3\n" \ - NOT_OP \ "\t" INSN "\t%0,%0,%z4\n" \ - "\tand\t%0,%0,%2\n" \ + AND_OP \ "\tor\t%@,%@,%0\n" \ "\tsc\t%@,%1\n" \ "\tbeq%?\t%@,%.,1b\n" \ "\tnop\n" \ "\tsync%-%]%>%)" -#define MIPS_SYNC_NEW_OP_12_NOT_NOP "" -#define MIPS_SYNC_NEW_OP_12_NOT_NOT "\tnor\t%0,%0,%.\n" +#define MIPS_SYNC_NEW_OP_12_AND "\tand\t%0,%0,%2\n" +#define MIPS_SYNC_NEW_OP_12_XOR "\txor\t%0,%0,%2\n" /* Return an asm string that atomically: @@ -3301,7 +3299,7 @@ while (0) /* Return an asm string that atomically: - - Sets memory reference %0 to ~%0 AND %1. + - Sets memory reference %0 to ~(%0 AND %1). SUFFIX is the suffix that should be added to "ll" and "sc" instructions. INSN is the and instruction needed to and a register @@ -3309,8 +3307,8 @@ while (0) #define MIPS_SYNC_NAND(SUFFIX, INSN) \ "%(%<%[%|sync\n" \ "1:\tll" SUFFIX "\t%@,%0\n" \ - "\tnor\t%@,%@,%.\n" \ "\t" INSN "\t%@,%@,%1\n" \ + "\tnor\t%@,%@,%.\n" \ "\tsc" SUFFIX "\t%@,%0\n" \ "\tbeq%?\t%@,%.,1b\n" \ "\tnop\n" \ @@ -3318,7 +3316,7 @@ while (0) /* Return an asm string that atomically: - - Sets memory reference %1 to ~%1 AND %2. + - Sets memory reference %1 to ~(%1 AND %2). - Sets register %0 to the old value of memory reference %1. @@ -3328,8 +3326,8 @@ while (0) #define MIPS_SYNC_OLD_NAND(SUFFIX, INSN) \ "%(%<%[%|sync\n" \ "1:\tll" SUFFIX "\t%0,%1\n" \ - "\tnor\t%@,%0,%.\n" \ - "\t" INSN "\t%@,%@,%2\n" \ + "\t" INSN "\t%@,%0,%2\n" \ + "\tnor\t%@,%@,%.\n" \ "\tsc" SUFFIX "\t%@,%1\n" \ "\tbeq%?\t%@,%.,1b\n" \ "\tnop\n" \ @@ -3337,7 +3335,7 @@ while (0) /* Return an asm string that atomically: - - Sets memory reference %1 to ~%1 AND %2. + - Sets memory reference %1 to ~(%1 AND %2). - Sets register %0 to the new value of memory reference %1. @@ -3347,11 +3345,11 @@ while (0) #define MIPS_SYNC_NEW_NAND(SUFFIX, INSN) \ "%(%<%[%|sync\n" \ "1:\tll" SUFFIX "\t%0,%1\n" \ - "\tnor\t%0,%0,%.\n" \ - "\t" INSN "\t%@,%0,%2\n" \ + "\t" INSN "\t%0,%0,%2\n" \ + "\tnor\t%@,%0,%.\n" \ "\tsc" SUFFIX "\t%@,%1\n" \ "\tbeq%?\t%@,%.,1b%~\n" \ - "\t" INSN "\t%0,%0,%2\n" \ + "\tnor\t%0,%0,%.\n" \ "\tsync%-%]%>%)" /* Return an asm string that atomically: diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index b9226c5c61..1b26f02985 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -5203,18 +5203,18 @@ [(set (pc) (if_then_else (equality_op (zero_extract:GPR - (match_operand:GPR 1 "register_operand" "d") + (match_operand:GPR 0 "register_operand" "d") (const_int 1) (match_operand 2 "const_int_operand" "")) (const_int 0)) - (label_ref (match_operand 0 "")) + (label_ref (match_operand 1 "")) (pc)))] "ISA_HAS_BBIT && UINTVAL (operands[2]) < GET_MODE_BITSIZE (mode)" { return mips_output_conditional_branch (insn, operands, - MIPS_BRANCH ("bbit", "%1,%2,%0"), - MIPS_BRANCH ("bbit", "%1,%2,%0")); + MIPS_BRANCH ("bbit", "%0,%2,%1"), + MIPS_BRANCH ("bbit", "%0,%2,%1")); } [(set_attr "type" "branch") (set_attr "mode" "none") @@ -5224,18 +5224,18 @@ [(set (pc) (if_then_else (equality_op (zero_extract:GPR - (match_operand:GPR 1 "register_operand" "d") + (match_operand:GPR 0 "register_operand" "d") (const_int 1) (match_operand 2 "const_int_operand" "")) (const_int 0)) (pc) - (label_ref (match_operand 0 ""))))] + (label_ref (match_operand 1 ""))))] "ISA_HAS_BBIT && UINTVAL (operands[2]) < GET_MODE_BITSIZE (mode)" { return mips_output_conditional_branch (insn, operands, - MIPS_BRANCH ("bbit", "%1,%2,%0"), - MIPS_BRANCH ("bbit", "%1,%2,%0")); + MIPS_BRANCH ("bbit", "%0,%2,%1"), + MIPS_BRANCH ("bbit", "%0,%2,%1")); } [(set_attr "type" "branch") (set_attr "mode" "none") diff --git a/gcc/config/mips/sync.md b/gcc/config/mips/sync.md index 286ca36921..f053be65b2 100644 --- a/gcc/config/mips/sync.md +++ b/gcc/config/mips/sync.md @@ -127,7 +127,7 @@ "GENERATE_LL_SC" { return (mips_output_sync_loop - (MIPS_SYNC_OP_12 ("", MIPS_SYNC_OP_12_NOT_NOP))); + (MIPS_SYNC_OP_12 ("", MIPS_SYNC_OP_12_AND))); } [(set_attr "length" "40")]) @@ -164,8 +164,7 @@ "GENERATE_LL_SC" { return (mips_output_sync_loop - (MIPS_SYNC_OLD_OP_12 ("", MIPS_SYNC_OLD_OP_12_NOT_NOP, - MIPS_SYNC_OLD_OP_12_NOT_NOP_REG))); + (MIPS_SYNC_OLD_OP_12 ("", MIPS_SYNC_OLD_OP_12_AND))); } [(set_attr "length" "40")]) @@ -207,7 +206,7 @@ "GENERATE_LL_SC" { return (mips_output_sync_loop - (MIPS_SYNC_NEW_OP_12 ("", MIPS_SYNC_NEW_OP_12_NOT_NOP))); + (MIPS_SYNC_NEW_OP_12 ("", MIPS_SYNC_NEW_OP_12_AND))); } [(set_attr "length" "40")]) @@ -239,9 +238,9 @@ "GENERATE_LL_SC" { return (mips_output_sync_loop - (MIPS_SYNC_OP_12 ("and", MIPS_SYNC_OP_12_NOT_NOT))); + (MIPS_SYNC_OP_12 ("and", MIPS_SYNC_OP_12_XOR))); } - [(set_attr "length" "44")]) + [(set_attr "length" "40")]) (define_expand "sync_old_nand" [(parallel [ @@ -274,10 +273,9 @@ "GENERATE_LL_SC" { return (mips_output_sync_loop - (MIPS_SYNC_OLD_OP_12 ("and", MIPS_SYNC_OLD_OP_12_NOT_NOT, - MIPS_SYNC_OLD_OP_12_NOT_NOT_REG))); + (MIPS_SYNC_OLD_OP_12 ("and", MIPS_SYNC_OLD_OP_12_XOR))); } - [(set_attr "length" "44")]) + [(set_attr "length" "40")]) (define_expand "sync_new_nand" [(parallel [ @@ -315,7 +313,7 @@ "GENERATE_LL_SC" { return (mips_output_sync_loop - (MIPS_SYNC_NEW_OP_12 ("and", MIPS_SYNC_NEW_OP_12_NOT_NOT))); + (MIPS_SYNC_NEW_OP_12 ("and", MIPS_SYNC_NEW_OP_12_XOR))); } [(set_attr "length" "40")]) diff --git a/gcc/config/rs6000/darwin-ldouble.c b/gcc/config/rs6000/darwin-ldouble.c index 15cac65c6e..b16389c555 100644 --- a/gcc/config/rs6000/darwin-ldouble.c +++ b/gcc/config/rs6000/darwin-ldouble.c @@ -387,7 +387,7 @@ fmsub (double a, double b, double c) FP_DECL_Q(V); FP_DECL_D(R); double r; - long double u, v, x, y, z; + long double u, x, y, z; FP_INIT_ROUNDMODE; FP_UNPACK_RAW_D (A, a); diff --git a/gcc/config/rs6000/linux-unwind.h b/gcc/config/rs6000/linux-unwind.h index 86392f4181..defdde60e6 100644 --- a/gcc/config/rs6000/linux-unwind.h +++ b/gcc/config/rs6000/linux-unwind.h @@ -162,10 +162,10 @@ get_regs (struct _Unwind_Context *context) /* li r0, 0x0077; sc (sigreturn new) */ /* li r0, 0x6666; sc (rt_sigreturn old) */ /* li r0, 0x00AC; sc (rt_sigreturn new) */ - if (*(unsigned int *) (pc + 4) != 0x44000002) + if (*(const unsigned int *) (pc + 4) != 0x44000002) return NULL; - if (*(unsigned int *) (pc + 0) == 0x38007777 - || *(unsigned int *) (pc + 0) == 0x38000077) + if (*(const unsigned int *) (pc + 0) == 0x38007777 + || *(const unsigned int *) (pc + 0) == 0x38000077) { struct sigframe { char gap[SIGNAL_FRAMESIZE]; @@ -174,8 +174,8 @@ get_regs (struct _Unwind_Context *context) } *frame = (struct sigframe *) context->cfa; return frame->regs; } - else if (*(unsigned int *) (pc + 0) == 0x38006666 - || *(unsigned int *) (pc + 0) == 0x380000AC) + else if (*(const unsigned int *) (pc + 0) == 0x38006666 + || *(const unsigned int *) (pc + 0) == 0x380000AC) { struct rt_sigframe { char gap[SIGNAL_FRAMESIZE + 16]; diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index 2598039587..1691fdba0f 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -1081,17 +1081,16 @@ ; (define_insn "movti" - [(set (match_operand:TI 0 "nonimmediate_operand" "=d,QS,d,o,Q") - (match_operand:TI 1 "general_operand" "QS,d,dPRT,d,Q"))] + [(set (match_operand:TI 0 "nonimmediate_operand" "=d,QS,d,o") + (match_operand:TI 1 "general_operand" "QS,d,dPRT,d"))] "TARGET_64BIT" "@ lmg\t%0,%N0,%S1 stmg\t%1,%N1,%S0 # - # #" - [(set_attr "op_type" "RSY,RSY,*,*,SS") - (set_attr "type" "lm,stm,*,*,*")]) + [(set_attr "op_type" "RSY,RSY,*,*") + (set_attr "type" "lm,stm,*,*")]) (define_split [(set (match_operand:TI 0 "nonimmediate_operand" "") @@ -1273,10 +1272,10 @@ (define_insn "*movdi_64" [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,d,d,d,d,f,d,d,d,d,d, - RT,!*f,!*f,!*f,!R,!T,b,Q,d,t,Q,t,?Q") + RT,!*f,!*f,!*f,!R,!T,b,Q,d,t,Q,t") (match_operand:DI 1 "general_operand" "K,N0HD0,N1HD0,N2HD0,N3HD0,Os,N0SD0,N1SD0,d,f,L,b,d,RT, - d,*f,R,T,*f,*f,d,K,t,d,t,Q,?Q"))] + d,*f,R,T,*f,*f,d,K,t,d,t,Q"))] "TARGET_64BIT" "@ lghi\t%0,%h1 @@ -1304,16 +1303,15 @@ # # stam\t%1,%N1,%S0 - lam\t%0,%N0,%S1 - #" + lam\t%0,%N0,%S1" [(set_attr "op_type" "RI,RI,RI,RI,RI,RIL,RIL,RIL,RRE,RRE,RXY,RIL,RRE,RXY, - RXY,RR,RX,RXY,RX,RXY,RIL,SIL,*,*,RS,RS,SS") + RXY,RR,RX,RXY,RX,RXY,RIL,SIL,*,*,RS,RS") (set_attr "type" "*,*,*,*,*,*,*,*,floaddf,floaddf,la,larl,lr,load,store, floaddf,floaddf,floaddf,fstoredf,fstoredf,larl,*,*,*, - *,*,*") + *,*") (set_attr "cpu_facility" "*,*,*,*,*,extimm,extimm,extimm,dfp,dfp,longdisp, z10,*,*,*,*,*,longdisp,*,longdisp, - z10,z10,*,*,*,*,*") + z10,z10,*,*,*,*") (set_attr "z10prop" "z10_fwd_A1, z10_fwd_E1, z10_fwd_E1, @@ -1339,7 +1337,6 @@ *, *, *, - *, *") ]) @@ -1378,9 +1375,9 @@ (define_insn "*movdi_31" [(set (match_operand:DI 0 "nonimmediate_operand" - "=d,d,Q,S,d ,o,!*f,!*f,!*f,!R,!T,Q,d") + "=d,d,Q,S,d ,o,!*f,!*f,!*f,!R,!T,d") (match_operand:DI 1 "general_operand" - " Q,S,d,d,dPRT,d, *f, R, T,*f,*f,Q,b"))] + " Q,S,d,d,dPRT,d, *f, R, T,*f,*f,b"))] "!TARGET_64BIT" "@ lm\t%0,%N0,%S1 @@ -1394,11 +1391,10 @@ ldy\t%0,%1 std\t%1,%0 stdy\t%1,%0 - # #" - [(set_attr "op_type" "RS,RSY,RS,RSY,*,*,RR,RX,RXY,RX,RXY,SS,*") - (set_attr "type" "lm,lm,stm,stm,*,*,floaddf,floaddf,floaddf,fstoredf,fstoredf,*,*") - (set_attr "cpu_facility" "*,*,*,*,*,*,*,*,*,*,*,*,z10")]) + [(set_attr "op_type" "RS,RSY,RS,RSY,*,*,RR,RX,RXY,RX,RXY,*") + (set_attr "type" "lm,lm,stm,stm,*,*,floaddf,floaddf,floaddf,fstoredf,fstoredf,*") + (set_attr "cpu_facility" "*,*,*,*,*,*,*,*,*,*,*,z10")]) ; For a load from a symbol ref we can use one of the target registers ; together with larl to load the address. @@ -1533,9 +1529,9 @@ (define_insn "*movsi_zarch" [(set (match_operand:SI 0 "nonimmediate_operand" - "=d,d,d,d,d,d,d,d,d,R,T,!*f,!*f,!*f,!R,!T,d,t,Q,b,Q,t,?Q") + "=d,d,d,d,d,d,d,d,d,R,T,!*f,!*f,!*f,!R,!T,d,t,Q,b,Q,t") (match_operand:SI 1 "general_operand" - "K,N0HS0,N1HS0,Os,L,b,d,R,T,d,d,*f,R,T,*f,*f,t,d,t,d,K,Q,?Q"))] + "K,N0HS0,N1HS0,Os,L,b,d,R,T,d,d,*f,R,T,*f,*f,t,d,t,d,K,Q"))] "TARGET_ZARCH" "@ lhi\t%0,%h1 @@ -1559,10 +1555,9 @@ stam\t%1,%1,%S0 strl\t%1,%0 mvhi\t%0,%1 - lam\t%0,%0,%S1 - #" + lam\t%0,%0,%S1" [(set_attr "op_type" "RI,RI,RI,RIL,RXY,RIL,RR,RX,RXY,RX,RXY, - RR,RX,RXY,RX,RXY,RRE,RRE,RS,RIL,SIL,RS,SS") + RR,RX,RXY,RX,RXY,RRE,RRE,RS,RIL,SIL,RS") (set_attr "type" "*, *, *, @@ -1584,10 +1579,9 @@ *, larl, *, - *, *") (set_attr "cpu_facility" "*,*,*,extimm,longdisp,z10,*,*,longdisp,*,longdisp, - *,*,longdisp,*,longdisp,*,*,*,z10,z10,*,*") + *,*,longdisp,*,longdisp,*,*,*,z10,z10,*") (set_attr "z10prop" "z10_fwd_A1, z10_fwd_E1, z10_fwd_E1, @@ -1609,12 +1603,11 @@ *, z10_rec, z10_super, - *, *")]) (define_insn "*movsi_esa" - [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,R,!*f,!*f,!R,d,t,Q,t,?Q") - (match_operand:SI 1 "general_operand" "K,d,R,d,*f,R,*f,t,d,t,Q,?Q"))] + [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,R,!*f,!*f,!R,d,t,Q,t") + (match_operand:SI 1 "general_operand" "K,d,R,d,*f,R,*f,t,d,t,Q"))] "!TARGET_ZARCH" "@ lhi\t%0,%h1 @@ -1627,10 +1620,9 @@ ear\t%0,%1 sar\t%0,%1 stam\t%1,%1,%S0 - lam\t%0,%0,%S1 - #" - [(set_attr "op_type" "RI,RR,RX,RX,RR,RX,RX,RRE,RRE,RS,RS,SS") - (set_attr "type" "*,lr,load,store,floadsf,floadsf,fstoresf,*,*,*,*,*") + lam\t%0,%0,%S1" + [(set_attr "op_type" "RI,RR,RX,RX,RR,RX,RX,RRE,RRE,RS,RS") + (set_attr "type" "*,lr,load,store,floadsf,floadsf,fstoresf,*,*,*,*") (set_attr "z10prop" "z10_fwd_A1, z10_fr_E1, z10_fwd_A3, @@ -1641,7 +1633,6 @@ z10_super_E1, z10_super, *, - *, *") ]) @@ -1752,8 +1743,8 @@ }) (define_insn "*movhi" - [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,d,d,R,T,b,Q,?Q") - (match_operand:HI 1 "general_operand" " d,n,R,T,b,d,d,d,K,?Q"))] + [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,d,d,R,T,b,Q") + (match_operand:HI 1 "general_operand" " d,n,R,T,b,d,d,d,K"))] "" "@ lr\t%0,%1 @@ -1764,11 +1755,10 @@ sth\t%1,%0 sthy\t%1,%0 sthrl\t%1,%0 - mvhhi\t%0,%1 - #" - [(set_attr "op_type" "RR,RI,RX,RXY,RIL,RX,RXY,RIL,SIL,SS") - (set_attr "type" "lr,*,*,*,larl,store,store,store,*,*") - (set_attr "cpu_facility" "*,*,*,*,z10,*,*,z10,z10,*") + mvhhi\t%0,%1" + [(set_attr "op_type" "RR,RI,RX,RXY,RIL,RX,RXY,RIL,SIL") + (set_attr "type" "lr,*,*,*,larl,store,store,store,*") + (set_attr "cpu_facility" "*,*,*,*,z10,*,*,z10,z10") (set_attr "z10prop" "z10_fr_E1, z10_fwd_A1, z10_super_E1, @@ -1777,8 +1767,7 @@ z10_super, z10_rec, z10_rec, - z10_super, - *")]) + z10_super")]) (define_peephole2 [(set (match_operand:HI 0 "register_operand" "") @@ -1813,8 +1802,8 @@ }) (define_insn "*movqi" - [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,d,R,T,Q,S,?Q") - (match_operand:QI 1 "general_operand" "d,n,R,T,d,d,n,n,?Q"))] + [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,d,R,T,Q,S") + (match_operand:QI 1 "general_operand" "d,n,R,T,d,d,n,n"))] "" "@ lr\t%0,%1 @@ -1824,10 +1813,9 @@ stc\t%1,%0 stcy\t%1,%0 mvi\t%S0,%b1 - mviy\t%S0,%b1 - #" - [(set_attr "op_type" "RR,RI,RX,RXY,RX,RXY,SI,SIY,SS") - (set_attr "type" "lr,*,*,*,store,store,store,store,*") + mviy\t%S0,%b1" + [(set_attr "op_type" "RR,RI,RX,RXY,RX,RXY,SI,SIY") + (set_attr "type" "lr,*,*,*,store,store,store,store") (set_attr "z10prop" "z10_fr_E1, z10_fwd_A1, z10_super_E1, @@ -1835,8 +1823,7 @@ z10_super, z10_rec, z10_super, - z10_super, - *")]) + z10_super")]) (define_peephole2 [(set (match_operand:QI 0 "nonimmediate_operand" "") @@ -1905,8 +1892,8 @@ "") (define_insn "*mov_64" - [(set (match_operand:TD_TF 0 "nonimmediate_operand" "=f,f,f,o, d,QS, d,o,Q") - (match_operand:TD_TF 1 "general_operand" " G,f,o,f,QS, d,dRT,d,Q"))] + [(set (match_operand:TD_TF 0 "nonimmediate_operand" "=f,f,f,o, d,QS, d,o") + (match_operand:TD_TF 1 "general_operand" " G,f,o,f,QS, d,dRT,d"))] "TARGET_64BIT" "@ lzxr\t%0 @@ -1916,23 +1903,21 @@ lmg\t%0,%N0,%S1 stmg\t%1,%N1,%S0 # - # #" - [(set_attr "op_type" "RRE,RRE,*,*,RSY,RSY,*,*,*") - (set_attr "type" "fsimptf,fsimptf,*,*,lm,stm,*,*,*")]) + [(set_attr "op_type" "RRE,RRE,*,*,RSY,RSY,*,*") + (set_attr "type" "fsimptf,fsimptf,*,*,lm,stm,*,*")]) (define_insn "*mov_31" - [(set (match_operand:TD_TF 0 "nonimmediate_operand" "=f,f,f,o,Q") - (match_operand:TD_TF 1 "general_operand" " G,f,o,f,Q"))] + [(set (match_operand:TD_TF 0 "nonimmediate_operand" "=f,f,f,o") + (match_operand:TD_TF 1 "general_operand" " G,f,o,f"))] "!TARGET_64BIT" "@ lzxr\t%0 lxr\t%0,%1 # - # #" - [(set_attr "op_type" "RRE,RRE,*,*,*") - (set_attr "type" "fsimptf,fsimptf,*,*,*")]) + [(set_attr "op_type" "RRE,RRE,*,*") + (set_attr "type" "fsimptf,fsimptf,*,*")]) ; TFmode in GPRs splitters @@ -2023,9 +2008,9 @@ (define_insn "*mov_64dfp" [(set (match_operand:DD_DF 0 "nonimmediate_operand" - "=f,f,f,d,f,f,R,T,d,d,RT,?Q") + "=f,f,f,d,f,f,R,T,d, d,RT") (match_operand:DD_DF 1 "general_operand" - "G,f,d,f,R,T,f,f,d,RT,d,?Q"))] + " G,f,d,f,R,T,f,f,d,RT, d"))] "TARGET_64BIT && TARGET_DFP" "@ lzdr\t%0 @@ -2038,11 +2023,10 @@ stdy\t%1,%0 lgr\t%0,%1 lg\t%0,%1 - stg\t%1,%0 - #" - [(set_attr "op_type" "RRE,RR,RRE,RRE,RX,RXY,RX,RXY,RRE,RXY,RXY,SS") + stg\t%1,%0" + [(set_attr "op_type" "RRE,RR,RRE,RRE,RX,RXY,RX,RXY,RRE,RXY,RXY") (set_attr "type" "fsimpdf,floaddf,floaddf,floaddf,floaddf,floaddf, - fstoredf,fstoredf,lr,load,store,*") + fstoredf,fstoredf,lr,load,store") (set_attr "z10prop" "*, *, *, @@ -2053,13 +2037,12 @@ *, z10_fr_E1, z10_fwd_A3, - z10_rec, - *") + z10_rec") ]) (define_insn "*mov_64" - [(set (match_operand:DD_DF 0 "nonimmediate_operand" "=f,f,f,f,R,T,d, d,RT,?Q") - (match_operand:DD_DF 1 "general_operand" "G,f,R,T,f,f,d,RT, d,?Q"))] + [(set (match_operand:DD_DF 0 "nonimmediate_operand" "=f,f,f,f,R,T,d, d,RT") + (match_operand:DD_DF 1 "general_operand" "G,f,R,T,f,f,d,RT, d"))] "TARGET_64BIT" "@ lzdr\t%0 @@ -2070,11 +2053,10 @@ stdy\t%1,%0 lgr\t%0,%1 lg\t%0,%1 - stg\t%1,%0 - #" - [(set_attr "op_type" "RRE,RR,RX,RXY,RX,RXY,RRE,RXY,RXY,SS") + stg\t%1,%0" + [(set_attr "op_type" "RRE,RR,RX,RXY,RX,RXY,RRE,RXY,RXY") (set_attr "type" "fsimp,fload,fload,fload, - fstore,fstore,lr,load,store,*") + fstore,fstore,lr,load,store") (set_attr "z10prop" "*, *, *, @@ -2083,14 +2065,13 @@ *, z10_fr_E1, z10_fwd_A3, - z10_rec, - *")]) + z10_rec")]) (define_insn "*mov_31" [(set (match_operand:DD_DF 0 "nonimmediate_operand" - "=f,f,f,f,R,T,d,d,Q,S, d,o,Q") + "=f,f,f,f,R,T,d,d,Q,S, d,o") (match_operand:DD_DF 1 "general_operand" - " G,f,R,T,f,f,Q,S,d,d,dPRT,d,Q"))] + " G,f,R,T,f,f,Q,S,d,d,dPRT,d"))] "!TARGET_64BIT" "@ lzdr\t%0 @@ -2104,11 +2085,10 @@ stm\t%1,%N1,%S0 stmy\t%1,%N1,%S0 # - # #" - [(set_attr "op_type" "RRE,RR,RX,RXY,RX,RXY,RS,RSY,RS,RSY,*,*,SS") + [(set_attr "op_type" "RRE,RR,RX,RXY,RX,RXY,RS,RSY,RS,RSY,*,*") (set_attr "type" "fsimp,fload,fload,fload, - fstore,fstore,lm,lm,stm,stm,*,*,*")]) + fstore,fstore,lm,lm,stm,stm,*,*")]) (define_split [(set (match_operand:DD_DF 0 "nonimmediate_operand" "") @@ -2157,9 +2137,9 @@ (define_insn "mov" [(set (match_operand:SD_SF 0 "nonimmediate_operand" - "=f,f,f,f,R,T,d,d,d,R,T,?Q") + "=f,f,f,f,R,T,d,d,d,R,T") (match_operand:SD_SF 1 "general_operand" - " G,f,R,T,f,f,d,R,T,d,d,?Q"))] + " G,f,R,T,f,f,d,R,T,d,d"))] "" "@ lzer\t%0 @@ -2172,11 +2152,10 @@ l\t%0,%1 ly\t%0,%1 st\t%1,%0 - sty\t%1,%0 - #" - [(set_attr "op_type" "RRE,RR,RX,RXY,RX,RXY,RR,RX,RXY,RX,RXY,SS") + sty\t%1,%0" + [(set_attr "op_type" "RRE,RR,RX,RXY,RX,RXY,RR,RX,RXY,RX,RXY") (set_attr "type" "fsimp,fload,fload,fload, - fstore,fstore,lr,load,load,store,store,*") + fstore,fstore,lr,load,load,store,store") (set_attr "z10prop" "*, *, *, @@ -2187,8 +2166,7 @@ z10_fwd_A3, z10_fwd_A3, z10_super, - z10_rec, - *")]) + z10_rec")]) ; ; movcc instruction pattern @@ -2222,21 +2200,6 @@ "mvc\t%O0(%2,%R0),%S1" [(set_attr "op_type" "SS")]) -(define_split - [(set (match_operand 0 "memory_operand" "") - (match_operand 1 "memory_operand" ""))] - "reload_completed - && GET_MODE (operands[0]) == GET_MODE (operands[1]) - && GET_MODE_SIZE (GET_MODE (operands[0])) > 0" - [(parallel - [(set (match_dup 0) (match_dup 1)) - (use (match_dup 2))])] -{ - operands[2] = GEN_INT (GET_MODE_SIZE (GET_MODE (operands[0]))); - operands[0] = adjust_address (operands[0], BLKmode, 0); - operands[1] = adjust_address (operands[1], BLKmode, 0); -}) - (define_peephole2 [(parallel [(set (match_operand:BLK 0 "memory_operand" "") diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index dab6ed0def..4b33059287 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,38 @@ +2008-12-10 Jason Merrill + + PR c++/35319 + * mangle.c (write_builtin_type): Add mangling for decimal floating + point and fixed point types. + (write_type): Pass FIXED_POINT_TYPE along. + +2008-12-09 Mark Mitchell + + PR c++/37971 + * class.c (resolve_address_of_overloaded_function): Check + accessibility of member functions unless FLAGS indicates + otherwise. + * call.c (standard_conversion): Adjust flags passed to + instantiate_type. + (convert_default_arg): Do not perform access checks. + * cp-tree.h (tsubst_flags_t): Add tf_no_access_control. + +2008-12-08 Steve Ellcey + + * decl2.c (mark_used): Remove assemble_external call. + +2008-12-08 Dodji Seketeli + + PR debug/38390 + * name-lookup.c (kept_level_p): Don't forget the case of levels + having using directives. + +2008-12-08 Richard Henderson + + PR 38240 + * class.c (finish_struct_bits): Use SET_TYPE_MODE. + * decl.c (record_unknown_type): Likewise. + (start_enum, finish_enum): Likewise. + 2008-12-05 Jakub Jelinek PR c++/35336 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 273599eddf..952e151f94 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -706,7 +706,10 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p, if ((TYPE_PTRFN_P (to) || TYPE_PTRMEMFUNC_P (to)) && expr && type_unknown_p (expr)) { - expr = instantiate_type (to, expr, tf_conv); + tsubst_flags_t tflags = tf_conv; + if (!(flags & LOOKUP_PROTECT)) + tflags |= tf_no_access_control; + expr = instantiate_type (to, expr, tflags); if (expr == error_mark_node) return NULL; from = TREE_TYPE (expr); @@ -1360,9 +1363,8 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags) /* Returns the implicit conversion sequence (see [over.ics]) from type FROM to type TO. The optional expression EXPR may affect the - conversion. FLAGS are the usual overloading flags. Only - LOOKUP_NO_CONVERSION is significant. If C_CAST_P is true, this - conversion is coming from a C-style cast. */ + conversion. FLAGS are the usual overloading flags. If C_CAST_P is + true, this conversion is coming from a C-style cast. */ static conversion * implicit_conversion (tree to, tree from, tree expr, bool c_cast_p, @@ -4954,8 +4956,17 @@ convert_default_arg (tree type, tree arg, tree fn, int parmnum) if (fn && DECL_TEMPLATE_INFO (fn)) arg = tsubst_default_argument (fn, type, arg); - arg = break_out_target_exprs (arg); + /* Due to: + + [dcl.fct.default] + The names in the expression are bound, and the semantic + constraints are checked, at the point where the default + expressions appears. + + we must not perform access checks here. */ + push_deferring_access_checks (dk_no_check); + arg = break_out_target_exprs (arg); if (TREE_CODE (arg) == CONSTRUCTOR) { arg = digest_init (type, arg); @@ -4978,6 +4989,7 @@ convert_default_arg (tree type, tree arg, tree fn, int parmnum) tf_warning_or_error); arg = convert_for_arg_passing (type, arg); } + pop_deferring_access_checks(); VEC_pop (tree, default_arg_context); diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 8553139979..805e51322e 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -1494,7 +1494,7 @@ finish_struct_bits (tree t) DECL_MODE (TYPE_MAIN_DECL (t)) = BLKmode; for (variants = t; variants; variants = TYPE_NEXT_VARIANT (variants)) { - TYPE_MODE (variants) = BLKmode; + SET_TYPE_MODE (variants, BLKmode); TREE_ADDRESSABLE (variants) = 1; } } @@ -5923,9 +5923,13 @@ pop_lang_context (void) control of FLAGS. Permit pointers to member function if FLAGS permits. If TEMPLATE_ONLY, the name of the overloaded function was a template-id, and EXPLICIT_TARGS are the explicitly provided - template arguments. If OVERLOAD is for one or more member - functions, then ACCESS_PATH is the base path used to reference - those member functions. */ + template arguments. + + If OVERLOAD is for one or more member functions, then ACCESS_PATH + is the base path used to reference those member functions. If + TF_NO_ACCESS_CONTROL is not set in FLAGS, and the address is + resolved to a member function, access checks will be performed and + errors issued if appropriate. */ static tree resolve_address_of_overloaded_function (tree target_type, @@ -6190,14 +6194,16 @@ resolve_address_of_overloaded_function (tree target_type, return error_mark_node; mark_used (fn); - /* We could not check access when this expression was originally - created since we did not know at that time to which function - the expression referred. */ - if (DECL_FUNCTION_MEMBER_P (fn)) - { - gcc_assert (access_path); - perform_or_defer_access_check (access_path, fn, fn); - } + } + + /* We could not check access to member functions when this + expression was originally created since we did not know at that + time to which function the expression referred. */ + if (!(flags & tf_no_access_control) + && DECL_FUNCTION_MEMBER_P (fn)) + { + gcc_assert (access_path); + perform_or_defer_access_check (access_path, fn, fn); } if (TYPE_PTRFN_P (target_type) || TYPE_PTRMEMFUNC_P (target_type)) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 7f33ff139b..bf22eb4d85 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -3560,20 +3560,22 @@ typedef enum linkage_kind { /* Bitmask flags to control type substitution. */ typedef enum tsubst_flags_t { - tf_none = 0, /* nothing special */ - tf_error = 1 << 0, /* give error messages */ - tf_warning = 1 << 1, /* give warnings too */ - tf_ignore_bad_quals = 1 << 2, /* ignore bad cvr qualifiers */ - tf_keep_type_decl = 1 << 3, /* retain typedef type decls - (make_typename_type use) */ - tf_ptrmem_ok = 1 << 4, /* pointers to member ok (internal - instantiate_type use) */ - tf_user = 1 << 5, /* found template must be a user template - (lookup_template_class use) */ - tf_conv = 1 << 6, /* We are determining what kind of - conversion might be permissible, - not actually performing the - conversion. */ + tf_none = 0, /* nothing special */ + tf_error = 1 << 0, /* give error messages */ + tf_warning = 1 << 1, /* give warnings too */ + tf_ignore_bad_quals = 1 << 2, /* ignore bad cvr qualifiers */ + tf_keep_type_decl = 1 << 3, /* retain typedef type decls + (make_typename_type use) */ + tf_ptrmem_ok = 1 << 4, /* pointers to member ok (internal + instantiate_type use) */ + tf_user = 1 << 5, /* found template must be a user template + (lookup_template_class use) */ + tf_conv = 1 << 6, /* We are determining what kind of + conversion might be permissible, + not actually performing the + conversion. */ + tf_no_access_control = 1 << 7, /* Do not perform access checks, even + when issuing other errors. */ /* Convenient substitution flags combinations. */ tf_warning_or_error = tf_warning | tf_error } tsubst_flags_t; diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 70ccd323f8..e786b39c8e 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -3199,7 +3199,7 @@ record_unknown_type (tree type, const char* name) TYPE_SIZE (type) = TYPE_SIZE (void_type_node); TYPE_ALIGN (type) = 1; TYPE_USER_ALIGN (type) = 0; - TYPE_MODE (type) = TYPE_MODE (void_type_node); + SET_TYPE_MODE (type, TYPE_MODE (void_type_node)); } /* A string for which we should create an IDENTIFIER_NODE at @@ -10912,7 +10912,7 @@ start_enum (tree name, tree underlying_type, bool scoped_enum_p) TYPE_MAX_VALUE (enumtype) = TYPE_MAX_VALUE (underlying_type); TYPE_SIZE (enumtype) = TYPE_SIZE (underlying_type); TYPE_SIZE_UNIT (enumtype) = TYPE_SIZE_UNIT (underlying_type); - TYPE_MODE (enumtype) = TYPE_MODE (underlying_type); + SET_TYPE_MODE (enumtype, TYPE_MODE (underlying_type)); TYPE_PRECISION (enumtype) = TYPE_PRECISION (underlying_type); TYPE_ALIGN (enumtype) = TYPE_ALIGN (underlying_type); TYPE_USER_ALIGN (enumtype) = TYPE_USER_ALIGN (underlying_type); @@ -11065,7 +11065,7 @@ finish_enum (tree enumtype) applied to the underlying type. */ TYPE_SIZE (enumtype) = TYPE_SIZE (underlying_type); TYPE_SIZE_UNIT (enumtype) = TYPE_SIZE_UNIT (underlying_type); - TYPE_MODE (enumtype) = TYPE_MODE (underlying_type); + SET_TYPE_MODE (enumtype, TYPE_MODE (underlying_type)); TYPE_ALIGN (enumtype) = TYPE_ALIGN (underlying_type); TYPE_USER_ALIGN (enumtype) = TYPE_USER_ALIGN (underlying_type); TYPE_UNSIGNED (enumtype) = TYPE_UNSIGNED (underlying_type); @@ -11133,7 +11133,7 @@ finish_enum (tree enumtype) TYPE_MAX_VALUE (t) = TYPE_MAX_VALUE (enumtype); TYPE_SIZE (t) = TYPE_SIZE (enumtype); TYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (enumtype); - TYPE_MODE (t) = TYPE_MODE (enumtype); + SET_TYPE_MODE (t, TYPE_MODE (enumtype)); TYPE_PRECISION (t) = TYPE_PRECISION (enumtype); TYPE_ALIGN (t) = TYPE_ALIGN (enumtype); TYPE_USER_ALIGN (t) = TYPE_USER_ALIGN (enumtype); diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index da9201e889..c8887257ec 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -3849,8 +3849,6 @@ mark_used (tree decl) note_vague_linkage_fn (decl); } - assemble_external (decl); - /* Is it a synthesized method that needs to be synthesized? */ if (TREE_CODE (decl) == FUNCTION_DECL && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl) diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index c0282d8ade..36b984e321 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -1598,6 +1598,7 @@ write_type (tree type) case BOOLEAN_TYPE: case INTEGER_TYPE: /* Includes wchar_t. */ case REAL_TYPE: + case FIXED_POINT_TYPE: { /* If this is a typedef, TYPE may not be one of the standard builtin type nodes, but an alias of one. Use @@ -1852,6 +1853,59 @@ write_builtin_type (tree type) gcc_unreachable (); break; + case FIXED_POINT_TYPE: + write_string ("DF"); + if (GET_MODE_IBIT (TYPE_MODE (type)) > 0) + write_unsigned_number (GET_MODE_IBIT (TYPE_MODE (type))); + if (type == fract_type_node + || type == sat_fract_type_node + || type == accum_type_node + || type == sat_accum_type_node) + write_char ('i'); + else if (type == unsigned_fract_type_node + || type == sat_unsigned_fract_type_node + || type == unsigned_accum_type_node + || type == sat_unsigned_accum_type_node) + write_char ('j'); + else if (type == short_fract_type_node + || type == sat_short_fract_type_node + || type == short_accum_type_node + || type == sat_short_accum_type_node) + write_char ('s'); + else if (type == unsigned_short_fract_type_node + || type == sat_unsigned_short_fract_type_node + || type == unsigned_short_accum_type_node + || type == sat_unsigned_short_accum_type_node) + write_char ('t'); + else if (type == long_fract_type_node + || type == sat_long_fract_type_node + || type == long_accum_type_node + || type == sat_long_accum_type_node) + write_char ('l'); + else if (type == unsigned_long_fract_type_node + || type == sat_unsigned_long_fract_type_node + || type == unsigned_long_accum_type_node + || type == sat_unsigned_long_accum_type_node) + write_char ('m'); + else if (type == long_long_fract_type_node + || type == sat_long_long_fract_type_node + || type == long_long_accum_type_node + || type == sat_long_long_accum_type_node) + write_char ('x'); + else if (type == unsigned_long_long_fract_type_node + || type == sat_unsigned_long_long_fract_type_node + || type == unsigned_long_long_accum_type_node + || type == sat_unsigned_long_long_accum_type_node) + write_char ('y'); + else + sorry ("mangling unknown fixed point type"); + write_unsigned_number (GET_MODE_FBIT (TYPE_MODE (type))); + if (TYPE_SATURATING (type)) + write_char ('s'); + else + write_char ('n'); + break; + default: gcc_unreachable (); } diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 0da373ce2a..b5d14b3b39 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -1548,7 +1548,8 @@ kept_level_p (void) return (current_binding_level->blocks != NULL_TREE || current_binding_level->keep || current_binding_level->kind == sk_cleanup - || current_binding_level->names != NULL_TREE); + || current_binding_level->names != NULL_TREE + || current_binding_level->using_directives); } /* Returns the kind of the innermost scope. */ diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 7e6da15515..66d28c77f9 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -338,7 +338,7 @@ Objective-C and Objective-C++ Dialects}. -finline-small-functions -fipa-cp -fipa-cp-clone -fipa-matrix-reorg -fipa-pta @gol -fipa-pure-const -fipa-reference -fipa-struct-reorg @gol -fipa-type-escape -fira -fira-algorithm=@var{algorithm} @gol --fira-coalesce -fno-ira-share-save-slots @gol +-fira-region=@var{region} -fira-coalesce -fno-ira-share-save-slots @gol -fno-ira-share-spill-slots -fira-verbose=@var{n} @gol -fivopts -fkeep-inline-functions -fkeep-static-consts @gol -floop-block -floop-interchange -floop-strip-mine @gol @@ -5728,17 +5728,25 @@ allocation. It is a default if @acronym{IRA} has been ported for the target. @item -fira-algorithm=@var{algorithm} -Use specified algorithm for the integrated register allocator. The -@var{algorithm} argument should be one of @code{regional}, @code{CB}, -or @code{mixed}. The second algorithm specifies Chaitin-Briggs -coloring, the first one specifies regional coloring based on -Chaitin-Briggs coloring, and the third one which is the default -specifies a mix of Chaitin-Briggs and regional algorithms where loops -with small register pressure are ignored. The first algorithm can -give best result for machines with small size and irregular register -set, the second one is faster and generates decent code and the -smallest size code, and the mixed algorithm usually give the best -results in most cases and for most architectures. +Use specified coloring algorithm for the integrated register +allocator. The @var{algorithm} argument should be @code{priority} or +@code{CB}. The first algorithm specifies Chow's priority coloring, +the second one specifies Chaitin-Briggs coloring. The second +algorithm can be unimplemented for some architectures. If it is +implemented, it is the default because Chaitin-Briggs coloring as a +rule generates a better code. + +@item -fira-region=@var{region} +Use specified regions for the integrated register allocator. The +@var{region} argument should be one of @code{all}, @code{mixed}, or +@code{one}. The first value means using all loops as register +allocation regions, the second value which is the default means using +all loops except for loops with small register pressure as the +regions, and third one means using all function as a single region. +The first value can give best result for machines with small size and +irregular register set, the third one results in faster and generates +decent code and the smallest size code, and the default value usually +give the best results in most cases and for most architectures. @item -fira-coalesce @opindex fira-coalesce diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 3505dea45a..50767a2036 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -2050,9 +2050,18 @@ Any MMX register. @item x Any SSE register. +@item Yz +First SSE register (@code{%xmm0}). + @ifset INTERNALS -@item Y -Any SSE2 register. +@item Y2 +Any SSE register, when SSE2 is enabled. + +@item Yi +Any SSE register, when SSE2 and inter-unit moves are enabled. + +@item Ym +Any MMX register, when inter-unit moves are enabled. @end ifset @item I diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi index 672f6d178a..3d3a52955b 100644 --- a/gcc/doc/sourcebuild.texi +++ b/gcc/doc/sourcebuild.texi @@ -1005,7 +1005,7 @@ the test @item variable @var{tool_timeout} defined by the set of tests -@item @var{gcc,,timeout} set in the target board +@item @var{gcc},@var{timeout} set in the target board @item 300 @end itemize diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 7dfb46b3a0..5a76a6e5e6 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -2841,7 +2841,8 @@ options have been processed. It is then re-examined by every call to The default implementation returns @code{IRA_COVER_CLASSES}, if defined, otherwise there is no default implementation. You must define either this macro or @code{IRA_COVER_CLASSES} in order to use the integrated register -allocator for the target. +allocator with Chaitin-Briggs coloring. If the macro is not defined, +the only available coloring algorithm is Chow's priority coloring. @end deftypefn @defmac IRA_COVER_CLASSES diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 68d0ee8da3..669948bc7c 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -110,6 +110,9 @@ static void dwarf2out_source_line (unsigned int, const char *); #define DWARF2_FRAME_REG_OUT(REGNO, FOR_EH) (REGNO) #endif +/* Save the result of dwarf2out_do_frame across PCH. */ +static GTY(()) bool saved_do_cfi_asm = 0; + /* Decide whether we want to emit frame unwind information for the current translation unit. */ @@ -121,7 +124,7 @@ dwarf2out_do_frame (void) we're not going to output frame or unwind info. */ return (write_symbols == DWARF2_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG - || DWARF2_FRAME_INFO + || DWARF2_FRAME_INFO || saved_do_cfi_asm #ifdef DWARF2_UNWIND_INFO || (DWARF2_UNWIND_INFO && (flag_unwind_tables @@ -142,7 +145,7 @@ dwarf2out_do_cfi_asm (void) #endif if (!flag_dwarf2_cfi_asm || !dwarf2out_do_frame ()) return false; - if (!eh_personality_libfunc) + if (saved_do_cfi_asm || !eh_personality_libfunc) return true; if (!HAVE_GAS_CFI_PERSONALITY_DIRECTIVE) return false; @@ -156,6 +159,7 @@ dwarf2out_do_cfi_asm (void) if ((enc & 0x70) != 0 && (enc & 0x70) != DW_EH_PE_pcrel) return false; + saved_do_cfi_asm = true; return true; } diff --git a/gcc/emutls.c b/gcc/emutls.c index c3374a1c7d..32e14a1c97 100644 --- a/gcc/emutls.c +++ b/gcc/emutls.c @@ -54,6 +54,9 @@ struct __emutls_array void **data[]; }; +void *__emutls_get_address (struct __emutls_object *); +void __emutls_register_common (struct __emutls_object *, word, word, void *); + #ifdef __GTHREADS #ifdef __GTHREAD_MUTEX_INIT static __gthread_mutex_t emutls_mutex = __GTHREAD_MUTEX_INIT; @@ -144,8 +147,12 @@ __emutls_get_address (struct __emutls_object *obj) static __gthread_once_t once = __GTHREAD_ONCE_INIT; __gthread_once (&once, emutls_init); __gthread_mutex_lock (&emutls_mutex); - offset = ++emutls_size; - obj->loc.offset = offset; + offset = obj->loc.offset; + if (offset == 0) + { + offset = ++emutls_size; + obj->loc.offset = offset; + } __gthread_mutex_unlock (&emutls_mutex); } diff --git a/gcc/final.c b/gcc/final.c index aceeb7cfb1..1735a73207 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -3440,7 +3440,10 @@ output_addr_const (FILE *file, rtx x) case SYMBOL_REF: if (SYMBOL_REF_DECL (x)) - mark_decl_referenced (SYMBOL_REF_DECL (x)); + { + mark_decl_referenced (SYMBOL_REF_DECL (x)); + assemble_external (SYMBOL_REF_DECL (x)); + } #ifdef ASM_OUTPUT_SYMBOL_REF ASM_OUTPUT_SYMBOL_REF (file, x); #else diff --git a/gcc/fixed-value.c b/gcc/fixed-value.c index 8c8d371904..d7f6413b29 100644 --- a/gcc/fixed-value.c +++ b/gcc/fixed-value.c @@ -291,9 +291,19 @@ do_fixed_add (FIXED_VALUE_TYPE *f, const FIXED_VALUE_TYPE *a, const FIXED_VALUE_TYPE *b, bool subtract_p, bool sat_p) { bool overflow_p = false; - double_int temp = subtract_p ? double_int_neg (b->data) : b->data; - bool unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (a->mode); - int i_f_bits = GET_MODE_IBIT (a->mode) + GET_MODE_FBIT (a->mode); + bool unsigned_p; + double_int temp; + int i_f_bits; + + /* This was a conditional expression but it triggered a bug in the + Solaris 8 compiler. */ + if (subtract_p) + temp = double_int_neg (b->data); + else + temp = b->data; + + unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (a->mode); + i_f_bits = GET_MODE_IBIT (a->mode) + GET_MODE_FBIT (a->mode); f->mode = a->mode; f->data = double_int_add (a->data, temp); if (unsigned_p) /* Unsigned type. */ diff --git a/gcc/flags.h b/gcc/flags.h index 4a209b32c1..0fff4f2acd 100644 --- a/gcc/flags.h +++ b/gcc/flags.h @@ -209,13 +209,22 @@ extern int flag_dump_rtl_in_asm; /* The algorithm used for the integrated register allocator (IRA). */ enum ira_algorithm { - IRA_ALGORITHM_REGIONAL, IRA_ALGORITHM_CB, - IRA_ALGORITHM_MIXED + IRA_ALGORITHM_PRIORITY }; extern enum ira_algorithm flag_ira_algorithm; +/* The regions used for the integrated register allocator (IRA). */ +enum ira_region +{ + IRA_REGION_ONE, + IRA_REGION_ALL, + IRA_REGION_MIXED +}; + +extern enum ira_region flag_ira_region; + extern unsigned int flag_ira_verbose; diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 7f53a8ee1d..db1fe42098 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,48 @@ +2008-12-12 Daniel Franke + + PR fortran/36355 + * check.c (gfc_check_matmul): Fixed error message for invalid + types to correctly identify the offending argument, added check + for mismatching types. + +2008-12-11 Richard Guenther + + * Make-lang.in (install-finclude-dir): Use correct mode argument + for mkinstalldirs. + +2008-12-09 Daniel Franke + + PR fortran/36376 + PR fortran/37468 + * lang-specs.h: Pass on -i* options to f951 to (probably) report + them as unknown. Duplicate gcc.c (cpp_options), but omit + -fpch-preprocess on -save-temps. + +2008-12-09 Daniel Franke + + PR fortran/36457 + * lang.opt: Added option idirafter. + * cpp.h (gfc_cpp_add_include_path_after): New prototype. + * cpp.c (gfc_cpp_handle_option): Recognize and handle OPT_dirafter. + (gfc_cpp_add_include_path_after): New, adds user-defined search path + after any other paths. + * invoke.texi (idirafter): New. + (no-range-check): Fixed entry in option-index. + +2008-12-09 Mikael Morin + + PR fortran/37469 + * expr.c (find_array_element): Simplify array bounds. + Assert that both bounds are constant expressions. + +2008-12-09 Mikael Morin + + PR fortran/35983 + * trans-expr.c (gfc_trans_subcomponent_assign): + Add se's pre and post blocks to current block. + (gfc_trans_structure_assign): Remove specific handling + of C_NULL_PTR and C_NULL_FUNPTR. + 2008-12-06 Jerry DeLisle PR fortran/38425 diff --git a/gcc/fortran/Make-lang.in b/gcc/fortran/Make-lang.in index ff5d03e65e..1600d18b36 100644 --- a/gcc/fortran/Make-lang.in +++ b/gcc/fortran/Make-lang.in @@ -211,7 +211,7 @@ doc/gfc-internals.pdf: $(GFC_INTERNALS_TEXI) # Create or recreate the gfortran private include file directory. install-finclude-dir: installdirs - $(mkinstalldirs) -m a+rx $(DESTDIR)$(libsubdir)/finclude + $(mkinstalldirs) -m 0755 $(DESTDIR)$(libsubdir)/finclude # # Install hooks: # f951 is installed elsewhere as part of $(COMPILERS). diff --git a/gcc/fortran/check.c b/gcc/fortran/check.c index de50767649..8ca67f2c49 100644 --- a/gcc/fortran/check.c +++ b/gcc/fortran/check.c @@ -1794,7 +1794,7 @@ gfc_check_malloc (gfc_expr *size) gfc_try gfc_check_matmul (gfc_expr *matrix_a, gfc_expr *matrix_b) { - if ((matrix_a->ts.type != BT_LOGICAL) && !gfc_numeric_ts (&matrix_b->ts)) + if ((matrix_a->ts.type != BT_LOGICAL) && !gfc_numeric_ts (&matrix_a->ts)) { gfc_error ("'%s' argument of '%s' intrinsic at %L must be numeric " "or LOGICAL", gfc_current_intrinsic_arg[0], @@ -1802,7 +1802,7 @@ gfc_check_matmul (gfc_expr *matrix_a, gfc_expr *matrix_b) return FAILURE; } - if ((matrix_b->ts.type != BT_LOGICAL) && !gfc_numeric_ts (&matrix_a->ts)) + if ((matrix_b->ts.type != BT_LOGICAL) && !gfc_numeric_ts (&matrix_b->ts)) { gfc_error ("'%s' argument of '%s' intrinsic at %L must be numeric " "or LOGICAL", gfc_current_intrinsic_arg[1], @@ -1810,6 +1810,15 @@ gfc_check_matmul (gfc_expr *matrix_a, gfc_expr *matrix_b) return FAILURE; } + if ((matrix_a->ts.type == BT_LOGICAL && gfc_numeric_ts (&matrix_b->ts)) + || (gfc_numeric_ts (&matrix_a->ts) && matrix_b->ts.type == BT_LOGICAL)) + { + gfc_error ("Argument types of '%s' intrinsic at %L must match (%s/%s)", + gfc_current_intrinsic, &matrix_a->where, + gfc_typename(&matrix_a->ts), gfc_typename(&matrix_b->ts)); + return FAILURE; + } + switch (matrix_a->rank) { case 1: diff --git a/gcc/fortran/cpp.c b/gcc/fortran/cpp.c index 51c8e8507c..d45d0c15b7 100644 --- a/gcc/fortran/cpp.c +++ b/gcc/fortran/cpp.c @@ -346,6 +346,10 @@ gfc_cpp_handle_option (size_t scode, const char *arg, int value ATTRIBUTE_UNUSED gfc_cpp_option.working_directory = value; break; + case OPT_idirafter: + gfc_cpp_add_include_path_after (xstrdup(arg), true); + break; + case OPT_imultilib: gfc_cpp_option.multilib = arg; break; @@ -634,6 +638,13 @@ gfc_cpp_add_include_path (char *path, bool user_supplied) } void +gfc_cpp_add_include_path_after (char *path, bool user_supplied) +{ + int cxx_aware = 0; + add_path (path, AFTER, cxx_aware, user_supplied); +} + +void gfc_cpp_register_include_paths (void) { int cxx_stdinc = 0; diff --git a/gcc/fortran/cpp.h b/gcc/fortran/cpp.h index db24502111..54a899f6a8 100644 --- a/gcc/fortran/cpp.h +++ b/gcc/fortran/cpp.h @@ -41,6 +41,7 @@ gfc_try gfc_cpp_preprocess (const char *source_file); void gfc_cpp_done (void); void gfc_cpp_add_include_path (char *path, bool user_supplied); +void gfc_cpp_add_include_path_after (char *path, bool user_supplied); void gfc_cpp_register_include_paths (void); diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c index 07dfc7a08a..4bdee7c6a8 100644 --- a/gcc/fortran/expr.c +++ b/gcc/fortran/expr.c @@ -1028,6 +1028,14 @@ find_array_element (gfc_constructor *cons, gfc_array_ref *ar, mpz_init_set_ui (span, 1); for (i = 0; i < ar->dimen; i++) { + if (gfc_reduce_init_expr (ar->as->lower[i]) == FAILURE + || gfc_reduce_init_expr (ar->as->upper[i]) == FAILURE) + { + t = FAILURE; + cons = NULL; + goto depart; + } + e = gfc_copy_expr (ar->start[i]); if (e->expr_type != EXPR_CONSTANT) { @@ -1035,14 +1043,15 @@ find_array_element (gfc_constructor *cons, gfc_array_ref *ar, goto depart; } + gcc_assert (ar->as->upper[i]->expr_type == EXPR_CONSTANT + && ar->as->lower[i]->expr_type == EXPR_CONSTANT); + /* Check the bounds. */ if ((ar->as->upper[i] - && ar->as->upper[i]->expr_type == EXPR_CONSTANT && mpz_cmp (e->value.integer, ar->as->upper[i]->value.integer) > 0) - || (ar->as->lower[i]->expr_type == EXPR_CONSTANT - && mpz_cmp (e->value.integer, - ar->as->lower[i]->value.integer) < 0)) + || (mpz_cmp (e->value.integer, + ar->as->lower[i]->value.integer) < 0)) { gfc_error ("Index in dimension %d is out of bounds " "at %L", i + 1, &ar->c_where[i]); diff --git a/gcc/fortran/invoke.texi b/gcc/fortran/invoke.texi index 8e47df4f68..675413cf6f 100644 --- a/gcc/fortran/invoke.texi +++ b/gcc/fortran/invoke.texi @@ -446,6 +446,15 @@ but this can be inhibited with the negated form in the command line, this option has no effect, since no @code{#line} directives are emitted whatsoever. +@item -idirafter @var{dir} +@opindex @code{idirafter @var{dir}} +@cindex preprocessing, include path +Search @var{dir} for include files, but do it after all directories +specified with @option{-I} and the standard system directories have +been exhausted. @var{dir} is treated as a system include directory. +If dir begins with @code{=}, then the @code{=} will be replaced by +the sysroot prefix; see @option{--sysroot} and @option{-isysroot}. + @item -imultilib @var{dir} @opindex @code{imultilib @var{dir}} @cindex preprocessing, include path @@ -977,7 +986,7 @@ variable override the default specified by @option{-fconvert}.} @item -fno-range-check -@opindex @code{-fno-range-check} +@opindex @code{fno-range-check} Disable range checking of input values during integer @code{READ} operations. For example, GNU Fortran will give an error if an input value is outside of the relevant range of [@code{-HUGE()}:@code{HUGE()}]. In other words, diff --git a/gcc/fortran/lang-specs.h b/gcc/fortran/lang-specs.h index a766162a5c..a622dcb1a6 100644 --- a/gcc/fortran/lang-specs.h +++ b/gcc/fortran/lang-specs.h @@ -20,13 +20,23 @@ /* This is the contribution to the `default_compilers' array in gcc.c for the f95 language. */ +/* Identical to gcc.c (cpp_options), but omitting %(cpp_unique_options) + and -fpch-preprocess on -save-temps. */ +#define CPP_ONLY_OPTIONS "%1 %{m*} %{f*} %{g*:%{!g0:%{g*} \ + %{!fno-working-directory:-fworking-directory}}} \ + %{std*&ansi&trigraphs} %{W*&pedantic*} %{w} \ + %{O*} %{undef}" -#define F951_CPP_OPTIONS "%{!nocpp: -cpp %g.f90 %(cpp_options)\ - %{E|M|MM:%(cpp_debug_options) -fsyntax-only} %{E}}" -#define F951_OPTIONS "%(cc1_options) %{J*} %{!cpp: %{I*}}\ - %{!nostdinc:-fintrinsic-modules-path finclude%s}\ - %{!fsyntax-only:%(invoke_as)}" -#define F951_SOURCE_FORM "%{!ffree-form:-ffixed-form}" +/* Options that f951 should know about, even if not preprocessing. */ +#define CPP_FORWARD_OPTIONS "%{i*} %{I*}" + +#define F951_CPP_OPTIONS "%{!nocpp: -cpp %g.f90 %{E} %(cpp_unique_options) \ + %{E|M|MM:%(cpp_debug_options) " CPP_ONLY_OPTIONS \ + " -fsyntax-only};: " CPP_FORWARD_OPTIONS "}" +#define F951_OPTIONS "%(cc1_options) %{J*} \ + %{!nostdinc:-fintrinsic-modules-path finclude%s}\ + %{!fsyntax-only:%(invoke_as)}" +#define F951_SOURCE_FORM "%{!ffree-form:-ffixed-form}" {".F", "@f77-cpp-input", 0, 0, 0}, @@ -36,14 +46,15 @@ {".FPP", "@f77-cpp-input", 0, 0, 0}, {"@f77-cpp-input", "f951 %i " F951_SOURCE_FORM " " \ - F951_CPP_OPTIONS " %{!E:" F951_OPTIONS "}", 0, 0, 0}, + F951_CPP_OPTIONS " %{!E:" F951_OPTIONS "}", 0, 0, 0}, {".f", "@f77", 0, 0, 0}, {".for", "@f77", 0, 0, 0}, {".ftn", "@f77", 0, 0, 0}, {"@f77", "f951 %i " F951_SOURCE_FORM " \ %{E:%{!cpp:%egfortran does not support -E without -cpp}} \ - %{cpp:" F951_CPP_OPTIONS "} %{!E:" F951_OPTIONS "}", 0, 0, 0}, + %{cpp:" F951_CPP_OPTIONS ";: " CPP_FORWARD_OPTIONS "} \ + %{!E:" F951_OPTIONS "}", 0, 0, 0}, {".F90", "@f95-cpp-input", 0, 0, 0}, {".F95", "@f95-cpp-input", 0, 0, 0}, {".F03", "@f95-cpp-input", 0, 0, 0}, @@ -54,11 +65,14 @@ {".f95", "@f95", 0, 0, 0}, {".f03", "@f95", 0, 0, 0}, {".f08", "@f95", 0, 0, 0}, -{"@f95", +{"@f95", "f951 %i %{E:%{!cpp:%egfortran does not support -E without -cpp}}\ - %{cpp:" F951_CPP_OPTIONS "} %{!E:" F951_OPTIONS "}", 0, 0, 0}, + %{cpp:" F951_CPP_OPTIONS ";: " CPP_FORWARD_OPTIONS "} \ + %{!E:" F951_OPTIONS "}", 0, 0, 0}, +#undef CPP_ONLY_OPTIONS +#undef CPP_FORWARD_OPTIONS #undef F951_SOURCE_FORM #undef F951_CPP_OPTIONS #undef F951_OPTIONS diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt index 04682c1911..e49ff76ee4 100644 --- a/gcc/fortran/lang.opt +++ b/gcc/fortran/lang.opt @@ -360,6 +360,10 @@ fworking-directory Fortran ; Documented in C +idirafter +Fortran Joined Separate +; Documented in C + imultilib Fortran Joined Separate ; Documented in C diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c index 5d3894c825..4ecfa0839d 100644 --- a/gcc/fortran/trans-expr.c +++ b/gcc/fortran/trans-expr.c @@ -3670,8 +3670,10 @@ gfc_trans_subcomponent_assign (tree dest, gfc_component * cm, gfc_expr * expr) { gfc_init_se (&se, NULL); gfc_conv_expr (&se, expr); + gfc_add_block_to_block (&block, &se.pre); gfc_add_modify (&block, dest, fold_convert (TREE_TYPE (dest), se.expr)); + gfc_add_block_to_block (&block, &se.post); } else { @@ -3713,21 +3715,8 @@ gfc_trans_structure_assign (tree dest, gfc_expr * expr) { /* Skip absent members in default initializers. */ if (!c->expr) - continue; + continue; - /* Update the type/kind of the expression if it represents either - C_NULL_PTR or C_NULL_FUNPTR. This is done here because this may - be the first place reached for initializing output variables that - have components of type C_PTR/C_FUNPTR that are initialized. */ - if (c->expr->ts.type == BT_DERIVED && c->expr->ts.derived - && c->expr->ts.derived->attr.is_iso_c) - { - c->expr->expr_type = EXPR_NULL; - c->expr->ts.type = c->expr->ts.derived->ts.type; - c->expr->ts.f90_type = c->expr->ts.derived->ts.f90_type; - c->expr->ts.kind = c->expr->ts.derived->ts.kind; - } - field = cm->backend_decl; tmp = fold_build3 (COMPONENT_REF, TREE_TYPE (field), dest, field, NULL_TREE); diff --git a/gcc/function.c b/gcc/function.c index 0320871f6a..29fe1b0b52 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -1766,7 +1766,9 @@ aggregate_value_p (const_tree exp, const_tree fntype) { case CALL_EXPR: fndecl = get_callee_fndecl (fntype); - fntype = fndecl ? TREE_TYPE (fndecl) : 0; + fntype = (fndecl + ? TREE_TYPE (fndecl) + : TREE_TYPE (CALL_EXPR_FN (fntype))); break; case FUNCTION_DECL: fndecl = fntype; @@ -3987,6 +3989,8 @@ allocate_struct_function (tree fndecl, bool abstract_p) OVERRIDE_ABI_FORMAT (fndecl); #endif + invoke_set_current_function_hook (fndecl); + if (fndecl != NULL_TREE) { DECL_STRUCT_FUNCTION (fndecl) = cfun; @@ -4012,8 +4016,6 @@ allocate_struct_function (tree fndecl, bool abstract_p) cfun->va_list_gpr_size = VA_LIST_MAX_GPR_SIZE; cfun->va_list_fpr_size = VA_LIST_MAX_FPR_SIZE; } - - invoke_set_current_function_hook (fndecl); } /* This is like allocate_struct_function, but pushes a new cfun for FNDECL diff --git a/gcc/function.h b/gcc/function.h index 16f2324abf..68df55e1a6 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -578,6 +578,7 @@ struct function GTY(()) unsigned int dont_save_pending_sizes_p : 1; unsigned int after_inlining : 1; + unsigned int always_inline_functions_inlined : 1; /* Fields below this point are not set for abstract functions; see allocate_struct_function. */ diff --git a/gcc/genpreds.c b/gcc/genpreds.c index bf53944e29..84b2e90d9e 100644 --- a/gcc/genpreds.c +++ b/gcc/genpreds.c @@ -959,7 +959,7 @@ write_enum_constraint_num (void) " CONSTRAINT__UNKNOWN = 0", stdout); FOR_ALL_CONSTRAINTS (c) printf (",\n CONSTRAINT_%s", c->c_name); - puts ("\n};\n"); + puts (",\n CONSTRAINT__LIMIT\n};\n"); } /* Write out a function which looks at a string and determines what diff --git a/gcc/gimple.c b/gcc/gimple.c index c0f8f1d530..90de9b3ebc 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -3108,8 +3108,11 @@ recalculate_side_effects (tree t) } break; + case tcc_constant: + /* No side-effects. */ + return; + default: - /* Can never be used with non-expressions. */ gcc_unreachable (); } } diff --git a/gcc/gimple.h b/gcc/gimple.h index debba122c9..8f8e49b61b 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -793,7 +793,7 @@ gimple gimple_build_asm_vec (const char *, VEC(tree,gc) *, VEC(tree,gc) *, VEC(tree,gc) *); gimple gimple_build_catch (tree, gimple_seq); gimple gimple_build_eh_filter (tree, gimple_seq); -gimple gimple_build_try (gimple_seq, gimple_seq, unsigned int); +gimple gimple_build_try (gimple_seq, gimple_seq, enum gimple_try_flags); gimple gimple_build_wce (gimple_seq); gimple gimple_build_resx (int); gimple gimple_build_switch (unsigned, tree, tree, ...); diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 2fea882811..e00024156f 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -3582,8 +3582,13 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, be dropped to memory, and then memcpy'd out. Don't do this for sparse arrays, though, as it's more efficient to follow the standard CONSTRUCTOR behavior of memset followed by - individual element initialization. */ - if (valid_const_initializer && !cleared) + individual element initialization. Also don't do this for small + all-zero initializers (which aren't big enough to merit + clearing), and don't try to make bitwise copies of + TREE_ADDRESSABLE types. */ + if (valid_const_initializer + && !(cleared || num_nonzero_elements == 0) + && !TREE_ADDRESSABLE (type)) { HOST_WIDE_INT size = int_size_in_bytes (type); unsigned int align; @@ -3605,7 +3610,9 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, else align = TYPE_ALIGN (type); - if (size > 0 && !can_move_by_pieces (size, align)) + if (size > 0 + && num_nonzero_elements > 1 + && !can_move_by_pieces (size, align)) { tree new_tree; diff --git a/gcc/graphite.c b/gcc/graphite.c index 8a464c19b3..877dffe281 100644 --- a/gcc/graphite.c +++ b/gcc/graphite.c @@ -51,6 +51,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-scalar-evolution.h" #include "tree-pass.h" #include "domwalk.h" +#include "value-prof.h" #include "pointer-set.h" #include "gimple.h" @@ -63,9 +64,9 @@ static VEC (scop_p, heap) *current_scops; /* Converts a GMP constant V to a tree and returns it. */ static tree -gmp_cst_to_tree (Value v) +gmp_cst_to_tree (tree type, Value v) { - return build_int_cst (integer_type_node, value_get_si (v)); + return build_int_cst (type, value_get_si (v)); } /* Debug the list of old induction variables for this SCOP. */ @@ -167,13 +168,9 @@ static tree loop_iv_stack_get_iv (loop_iv_stack stack, int index) { iv_stack_entry_p entry = VEC_index (iv_stack_entry_p, *stack, index); + iv_stack_entry_data data = entry->data; - tree result = NULL; - - if (entry->kind != iv_stack_entry_const) - result = entry->data.iv->t; - - return result; + return iv_stack_entry_is_iv (entry) ? data.iv->t : data.constant; } /* Get the IV from its NAME in STACK. */ @@ -247,6 +244,98 @@ free_loop_iv_stack (loop_iv_stack stack) VEC_free (iv_stack_entry_p, heap, *stack); } + + +/* Structure containing the mapping between the CLooG's induction + variable and the type of the old induction variable. */ +typedef struct ivtype_map_elt +{ + tree type; + const char *cloog_iv; +} *ivtype_map_elt; + +/* Print to stderr the element ELT. */ + +static void +debug_ivtype_elt (ivtype_map_elt elt) +{ + fprintf (stderr, "(%s, ", elt->cloog_iv); + print_generic_expr (stderr, elt->type, 0); + fprintf (stderr, ")\n"); +} + +/* Helper function for debug_ivtype_map. */ + +static int +debug_ivtype_map_1 (void **slot, void *s ATTRIBUTE_UNUSED) +{ + struct ivtype_map_elt *entry = (struct ivtype_map_elt *) *slot; + debug_ivtype_elt (entry); + return 1; +} + +/* Print to stderr all the elements of MAP. */ + +void +debug_ivtype_map (htab_t map) +{ + htab_traverse (map, debug_ivtype_map_1, NULL); +} + +/* Constructs a new SCEV_INFO_STR structure for VAR and INSTANTIATED_BELOW. */ + +static inline ivtype_map_elt +new_ivtype_map_elt (const char *cloog_iv, tree type) +{ + ivtype_map_elt res; + + res = XNEW (struct ivtype_map_elt); + res->cloog_iv = cloog_iv; + res->type = type; + + return res; +} + +/* Computes a hash function for database element ELT. */ + +static hashval_t +ivtype_map_elt_info (const void *elt) +{ + return htab_hash_pointer (((const struct ivtype_map_elt *) elt)->cloog_iv); +} + +/* Compares database elements E1 and E2. */ + +static int +eq_ivtype_map_elts (const void *e1, const void *e2) +{ + const struct ivtype_map_elt *elt1 = (const struct ivtype_map_elt *) e1; + const struct ivtype_map_elt *elt2 = (const struct ivtype_map_elt *) e2; + + return (elt1->cloog_iv == elt2->cloog_iv); +} + + + +/* Given a CLOOG_IV, returns the type that it should have in GCC land. + If the information is not available, i.e. in the case one of the + transforms created the loop, just return integer_type_node. */ + +static tree +gcc_type_for_cloog_iv (const char *cloog_iv, graphite_bb_p gbb) +{ + struct ivtype_map_elt tmp; + PTR *slot; + + tmp.cloog_iv = cloog_iv; + slot = htab_find_slot (GBB_CLOOG_IV_TYPES (gbb), &tmp, NO_INSERT); + + if (slot && *slot) + return ((ivtype_map_elt) *slot)->type; + + return integer_type_node; +} + /* Inserts constants derived from the USER_STMT argument list into the STACK. This is needed to map old ivs to constants when loops have been eliminated. */ @@ -257,16 +346,23 @@ loop_iv_stack_patch_for_consts (loop_iv_stack stack, { struct clast_stmt *t; int index = 0; + CloogStatement *cs = user_stmt->statement; + graphite_bb_p gbb = (graphite_bb_p) cloog_statement_usr (cs); + for (t = user_stmt->substitutions; t; t = t->next) { - struct clast_term *term = (struct clast_term*) + struct clast_expr *expr = (struct clast_expr *) ((struct clast_assignment *)t)->RHS; + struct clast_term *term = (struct clast_term *) expr; /* FIXME: What should be done with expr_bin, expr_red? */ - if (((struct clast_assignment *)t)->RHS->type == expr_term + if (expr->type == expr_term && !term->var) { - tree value = gmp_cst_to_tree (term->val); + loop_p loop = gbb_loop_at_index (gbb, index); + tree oldiv = oldiv_for_loop (GBB_SCOP (gbb), loop); + tree type = oldiv ? TREE_TYPE (oldiv) : integer_type_node; + tree value = gmp_cst_to_tree (type, term->val); loop_iv_stack_insert_constant (stack, index, value); } index = index + 1; @@ -293,33 +389,6 @@ loop_iv_stack_remove_constants (loop_iv_stack stack) } } -/* In SCOP, get the induction variable from NAME. OLD is the original - loop that contained the definition of NAME. */ - -static name_tree -get_old_iv_from_ssa_name (scop_p scop, loop_p old, tree name) -{ - tree var = SSA_NAME_VAR (name); - int i; - name_tree oldiv; - - for (i = 0; VEC_iterate (name_tree, SCOP_OLDIVS (scop), i, oldiv); i++) - { - loop_p current = old; - - while (current) - { - if (var == oldiv->t - && oldiv->loop == current) - return oldiv; - - current = loop_outer (current); - } - } - return NULL; - -} - /* Returns a new loop_to_cloog_loop_str structure. */ static inline struct loop_to_cloog_loop_str * @@ -495,7 +564,7 @@ print_graphite_bb (FILE *file, graphite_bb_p gb, int indent, int verbosity) if (GBB_DOMAIN (gb)) { fprintf (file, " (domain: \n"); - cloog_matrix_print (dump_file, GBB_DOMAIN (gb)); + cloog_matrix_print (file, GBB_DOMAIN (gb)); fprintf (file, " )\n"); } @@ -525,7 +594,7 @@ print_graphite_bb (FILE *file, graphite_bb_p gb, int indent, int verbosity) if (GBB_CONDITIONS (gb)) { fprintf (file, " (conditions: \n"); - dump_gbb_conditions (dump_file, gb); + dump_gbb_conditions (file, gb); fprintf (file, " )\n"); } @@ -610,14 +679,6 @@ debug_scops (int verbosity) print_scops (stderr, verbosity); } -/* Return true when BB is contained in SCOP. */ - -static inline bool -bb_in_scop_p (basic_block bb, scop_p scop) -{ - return bitmap_bit_p (SCOP_BBS_B (scop), bb->index); -} - /* Pretty print to FILE the SCOP in DOT format. */ static void @@ -818,15 +879,6 @@ dot_all_scops (void) #endif } -/* Returns true when LOOP is in SCOP. */ - -static inline bool -loop_in_scop_p (struct loop *loop, scop_p scop) -{ - return (bb_in_scop_p (loop->header, scop) - && bb_in_scop_p (loop->latch, scop)); -} - /* Returns the outermost loop in SCOP that contains BB. */ static struct loop * @@ -1025,23 +1077,87 @@ harmful_stmt_in_bb (basic_block scop_entry, basic_block bb) return NULL; } +/* Returns true when BB will be represented in graphite. Return false + for the basic blocks that contain code eliminated in the code + generation pass: i.e. induction variables and exit conditions. */ + +static bool +graphite_stmt_p (scop_p scop, basic_block bb, + VEC (data_reference_p, heap) *drs) +{ + gimple_stmt_iterator gsi; + loop_p loop = bb->loop_father; + + if (VEC_length (data_reference_p, drs) > 0) + return true; + + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + gimple stmt = gsi_stmt (gsi); + + switch (gimple_code (stmt)) + { + /* Control flow expressions can be ignored, as they are + represented in the iteration domains and will be + regenerated by graphite. */ + case GIMPLE_COND: + case GIMPLE_GOTO: + case GIMPLE_SWITCH: + break; + + case GIMPLE_ASSIGN: + { + tree var = gimple_assign_lhs (stmt); + var = analyze_scalar_evolution (loop, var); + var = instantiate_scev (block_before_scop (scop), loop, var); + + if (chrec_contains_undetermined (var)) + return true; + + break; + } + + default: + return true; + } + } + + return false; +} + /* Store the GRAPHITE representation of BB. */ static void new_graphite_bb (scop_p scop, basic_block bb) { - struct graphite_bb *gbb = XNEW (struct graphite_bb); + struct graphite_bb *gbb; + VEC (data_reference_p, heap) *drs = VEC_alloc (data_reference_p, heap, 5); + struct loop *nest = outermost_loop_in_scop (scop, bb); + gimple_stmt_iterator gsi; + + bitmap_set_bit (SCOP_BBS_B (scop), bb->index); + + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + find_data_references_in_stmt (nest, gsi_stmt (gsi), &drs); + + if (!graphite_stmt_p (scop, bb, drs)) + { + free_data_refs (drs); + return; + } + gbb = XNEW (struct graphite_bb); bb->aux = gbb; GBB_BB (gbb) = bb; GBB_SCOP (gbb) = scop; - GBB_DATA_REFS (gbb) = NULL; + GBB_DATA_REFS (gbb) = drs; GBB_DOMAIN (gbb) = NULL; GBB_CONDITIONS (gbb) = NULL; GBB_CONDITION_CASES (gbb) = NULL; GBB_LOOPS (gbb) = NULL; + GBB_STATIC_SCHEDULE (gbb) = NULL; + GBB_CLOOG_IV_TYPES (gbb) = NULL; VEC_safe_push (graphite_bb_p, heap, SCOP_BBS (scop), gbb); - bitmap_set_bit (SCOP_BBS_B (scop), bb->index); } /* Frees GBB. */ @@ -1052,15 +1168,41 @@ free_graphite_bb (struct graphite_bb *gbb) if (GBB_DOMAIN (gbb)) cloog_matrix_free (GBB_DOMAIN (gbb)); - free_data_refs (GBB_DATA_REFS (gbb)); + if (GBB_CLOOG_IV_TYPES (gbb)) + htab_delete (GBB_CLOOG_IV_TYPES (gbb)); + + /* FIXME: free_data_refs is disabled for the moment, but should be + enabled. + + free_data_refs (GBB_DATA_REFS (gbb)); */ + VEC_free (gimple, heap, GBB_CONDITIONS (gbb)); VEC_free (gimple, heap, GBB_CONDITION_CASES (gbb)); VEC_free (loop_p, heap, GBB_LOOPS (gbb)); - GBB_BB (gbb)->aux = 0; XDELETE (gbb); } +/* Register basic blocks belonging to a region in a pointer set. */ + +static void +register_bb_in_sese (basic_block entry_bb, basic_block exit_bb, sese region) +{ + edge_iterator ei; + edge e; + basic_block bb = entry_bb; + + FOR_EACH_EDGE (e, ei, bb->succs) + { + if (!pointer_set_contains (SESE_REGION_BBS (region), e->dest) && + e->dest->index != exit_bb->index) + { + pointer_set_insert (SESE_REGION_BBS (region), e->dest); + register_bb_in_sese (e->dest, exit_bb, region); + } + } +} + /* Creates a new scop starting with ENTRY. */ static scop_p @@ -1073,11 +1215,15 @@ new_scop (edge entry, edge exit) SCOP_REGION (scop) = XNEW (struct sese); SESE_ENTRY (SCOP_REGION (scop)) = entry; SESE_EXIT (SCOP_REGION (scop)) = exit; + SESE_REGION_BBS (SCOP_REGION (scop)) = pointer_set_create (); + register_bb_in_sese (SCOP_ENTRY (scop), SCOP_EXIT (scop), + SCOP_REGION (scop)); SCOP_BBS (scop) = VEC_alloc (graphite_bb_p, heap, 3); SCOP_OLDIVS (scop) = VEC_alloc (name_tree, heap, 3); SCOP_BBS_B (scop) = BITMAP_ALLOC (NULL); SCOP_LOOPS (scop) = BITMAP_ALLOC (NULL); SCOP_LOOP_NEST (scop) = VEC_alloc (loop_p, heap, 3); + SCOP_ADD_PARAMS (scop) = true; SCOP_PARAMS (scop) = VEC_alloc (name_tree, heap, 3); SCOP_PROG (scop) = cloog_program_malloc (); cloog_program_set_names (SCOP_PROG (scop), cloog_names_malloc ()); @@ -1318,7 +1464,7 @@ scopdet_basic_block_info (basic_block bb, VEC (sd_region, heap) **scops, case GBB_LOOP_MULT_EXIT_HEADER: { - /* XXX: For now we just do not join loops with multiple exits. If the + /* XXX: For now we just do not join loops with multiple exits. If the exits lead to the same bb it may be possible to join the loop. */ VEC (sd_region, heap) *tmp_scops = VEC_alloc (sd_region, heap, 3); VEC (edge, heap) *exits = get_loop_exit_edges (loop); @@ -1326,28 +1472,27 @@ scopdet_basic_block_info (basic_block bb, VEC (sd_region, heap) **scops, int i; build_scops_1 (bb, &tmp_scops, loop); - - /* Start at all bbs dominated by a loop exit that only exists in this - loop. */ + /* Scan the code dominated by this loop. This means all bbs, that are + are dominated by a bb in this loop, but are not part of this loop. + + The easiest case: + - The loop exit destination is dominated by the exit sources. + + TODO: We miss here the more complex cases: + - The exit destinations are dominated by another bb inside the + loop. + - The loop dominates bbs, that are not exit destinations. */ for (i = 0; VEC_iterate (edge, exits, i, e); i++) - if (e->src->loop_father == loop) - { - VEC (basic_block, heap) *dominated; - basic_block b; - int j; - dominated = get_dominated_by (CDI_DOMINATORS, e->src); - for (j = 0; VEC_iterate (basic_block, dominated, j, b); j++) - /* Loop exit. */ - if (loop_depth (find_common_loop (loop, b->loop_father)) - < loop_depth (loop)) - { - /* Pass loop_outer to recognize b as loop header in - build_scops_1. */ - if (b->loop_father->header == b) - build_scops_1 (b, &tmp_scops, loop_outer (b->loop_father)); - else - build_scops_1 (b, &tmp_scops, b->loop_father); - } + if (e->src->loop_father == loop + && dominated_by_p (CDI_DOMINATORS, e->dest, e->src)) + { + /* Pass loop_outer to recognize e->dest as loop header in + build_scops_1. */ + if (e->dest->loop_father->header == e->dest) + build_scops_1 (e->dest, &tmp_scops, + loop_outer (e->dest->loop_father)); + else + build_scops_1 (e->dest, &tmp_scops, e->dest->loop_father); } result.next = NULL; @@ -1500,7 +1645,6 @@ scopdet_basic_block_info (basic_block bb, VEC (sd_region, heap) **scops, static struct scopdet_info build_scops_1 (basic_block current, VEC (sd_region, heap) **scops, loop_p loop) { - bool in_scop = false; sd_region open_scop; struct scopdet_info sinfo; @@ -1512,6 +1656,8 @@ build_scops_1 (basic_block current, VEC (sd_region, heap) **scops, loop_p loop) result.next = NULL; result.last = NULL; open_scop.entry = NULL; + open_scop.exit = NULL; + sinfo.last = NULL; /* Loop over the dominance tree. If we meet a difficult bb, close the current SCoP. Loop and condition header start a new layer, @@ -1800,6 +1946,29 @@ mark_exit_edges (VEC (sd_region, heap) *regions) e->aux = s; } +/* Free and compute again all the dominators information. */ + +static inline void +recompute_all_dominators (void) +{ + free_dominance_info (CDI_DOMINATORS); + free_dominance_info (CDI_POST_DOMINATORS); + calculate_dominance_info (CDI_DOMINATORS); + calculate_dominance_info (CDI_POST_DOMINATORS); +} + +/* Verifies properties that GRAPHITE should maintain during translation. */ + +static inline void +graphite_verify (void) +{ +#ifdef ENABLE_CHECKING + verify_loop_structure (); + verify_dominators (CDI_DOMINATORS); + verify_dominators (CDI_POST_DOMINATORS); + verify_ssa (false); +#endif +} /* Create for all scop regions a single entry and a single exit edge. */ @@ -1938,64 +2107,108 @@ build_scop_bbs (scop_p scop) sbitmap_free (visited); } +/* Returns the number of reduction phi nodes in LOOP. */ -/* Record LOOP as occuring in SCOP. */ +static int +nb_reductions_in_loop (loop_p loop) +{ + int res = 0; + gimple_stmt_iterator gsi; -static void -scop_record_loop (scop_p scop, struct loop *loop) + for (gsi = gsi_start_phis (loop->header); !gsi_end_p (gsi); gsi_next (&gsi)) + { + gimple phi = gsi_stmt (gsi); + tree scev; + + if (!is_gimple_reg (PHI_RESULT (phi))) + continue; + + scev = analyze_scalar_evolution (loop, PHI_RESULT (phi)); + scev = instantiate_parameters (loop, scev); + if (chrec_contains_undetermined (scev)) + res++; + } + + return res; +} + +/* A LOOP is in normal form when it contains only one scalar phi node + that defines the main induction variable of the loop, only one + increment of the IV, and only one exit condition. */ + +static tree +graphite_loop_normal_form (loop_p loop) { - loop_p parent; - tree induction_var; + struct tree_niter_desc niter; + tree nit; + gimple_seq stmts; + edge exit = single_dom_exit (loop); - if (bitmap_bit_p (SCOP_LOOPS (scop), loop->num)) - return; + if (!number_of_iterations_exit (loop, exit, &niter, false)) + gcc_unreachable (); - parent = loop_outer (loop); - induction_var = find_induction_var_from_exit_cond (loop); + nit = force_gimple_operand (unshare_expr (niter.niter), &stmts, true, + NULL_TREE); + if (stmts) + gsi_insert_seq_on_edge_immediate (loop_preheader_edge (loop), stmts); - if (!bb_in_scop_p (parent->latch, scop)) - parent = NULL; + /* One IV per loop. */ + if (nb_reductions_in_loop (loop) > 0) + return NULL_TREE; - if (induction_var != NULL_TREE) - { - name_tree oldiv = XNEW (struct name_tree); - oldiv->t = SSA_NAME_VAR (induction_var); - if (DECL_NAME (oldiv->t)) - oldiv->name = IDENTIFIER_POINTER (DECL_NAME (oldiv->t)); - else - { - int len = 2 + 16; - char *n = XNEWVEC (char, len); - snprintf (n, len, "D.%u", DECL_UID (oldiv->t)); - oldiv->name = n; - } - oldiv->loop = loop; + return canonicalize_loop_ivs (loop, NULL, nit); +} - VEC_safe_push (name_tree, heap, SCOP_OLDIVS (scop), oldiv); - } +/* Record LOOP as occuring in SCOP. Returns true when the operation + was successful. */ + +static bool +scop_record_loop (scop_p scop, loop_p loop) +{ + tree induction_var; + name_tree oldiv; + + if (bitmap_bit_p (SCOP_LOOPS (scop), loop->num)) + return true; bitmap_set_bit (SCOP_LOOPS (scop), loop->num); VEC_safe_push (loop_p, heap, SCOP_LOOP_NEST (scop), loop); + + induction_var = graphite_loop_normal_form (loop); + if (!induction_var) + return false; + + oldiv = XNEW (struct name_tree); + oldiv->t = induction_var; + oldiv->name = get_name (SSA_NAME_VAR (oldiv->t)); + oldiv->loop = loop; + VEC_safe_push (name_tree, heap, SCOP_OLDIVS (scop), oldiv); + return true; } -/* Build the loop nests contained in SCOP. */ +/* Build the loop nests contained in SCOP. Returns true when the + operation was successful. */ -static void +static bool build_scop_loop_nests (scop_p scop) { unsigned i; - graphite_bb_p gb; + basic_block bb; struct loop *loop0, *loop1; - for (i = 0; VEC_iterate (graphite_bb_p, SCOP_BBS (scop), i, gb); i++) - { - struct loop *loop = gbb_loop (gb); + FOR_EACH_BB (bb) + if (bb_in_scop_p (bb, scop)) + { + struct loop *loop = bb->loop_father; - /* Only add loops, if they are completely contained in the SCoP. */ - if (loop->header == GBB_BB (gb) - && bb_in_scop_p (loop->latch, scop)) - scop_record_loop (scop, gbb_loop (gb)); - } + /* Only add loops if they are completely contained in the SCoP. */ + if (loop->header == bb + && bb_in_scop_p (loop->latch, scop)) + { + if (!scop_record_loop (scop, loop)) + return false; + } + } /* Make sure that the loops in the SCOP_LOOP_NEST are ordered. It can be the case that an inner loop is inserted before an outer @@ -2012,20 +2225,37 @@ build_scop_loop_nests (scop_p scop) VEC_replace (loop_p, SCOP_LOOP_NEST (scop), i + 1, loop0); } } + + return true; } -/* Calculate the number of loops around GB in the current SCOP. */ +/* Build dynamic schedules for all the BBs. */ -static inline int -nb_loops_around_gb (graphite_bb_p gb) +static void +build_scop_dynamic_schedules (scop_p scop) { - scop_p scop = GBB_SCOP (gb); - struct loop *l = gbb_loop (gb); - int d = 0; + int i, dim, loop_num, row, col; + graphite_bb_p gb; - for (; loop_in_scop_p (l, scop); d++, l = loop_outer (l)); + for (i = 0; VEC_iterate (graphite_bb_p, SCOP_BBS (scop), i, gb); i++) + { + loop_num = GBB_BB (gb)->loop_father->num; - return d; + if (loop_num != 0) + { + dim = nb_loops_around_gb (gb); + GBB_DYNAMIC_SCHEDULE (gb) = cloog_matrix_alloc (dim, dim); + + for (row = 0; row < GBB_DYNAMIC_SCHEDULE (gb)->NbRows; row++) + for (col = 0; col < GBB_DYNAMIC_SCHEDULE (gb)->NbColumns; col++) + if (row == col) + value_set_si (GBB_DYNAMIC_SCHEDULE (gb)->p[row][col], 1); + else + value_set_si (GBB_DYNAMIC_SCHEDULE (gb)->p[row][col], 0); + } + else + GBB_DYNAMIC_SCHEDULE (gb) = NULL; + } } /* Build for BB the static schedule. @@ -2139,6 +2369,8 @@ param_index (tree var, scop_p scop) if (p->t == var) return i; + gcc_assert (SCOP_ADD_PARAMS (scop)); + nvar = XNEW (struct name_tree); nvar->t = var; nvar->name = NULL; @@ -2218,26 +2450,28 @@ scan_tree_for_params (scop_p s, tree e, CloogMatrix *c, int r, Value k, case MULT_EXPR: if (chrec_contains_symbols (TREE_OPERAND (e, 0))) { - Value val; - - gcc_assert (host_integerp (TREE_OPERAND (e, 1), 0)); - - value_init (val); - value_set_si (val, int_cst_value (TREE_OPERAND (e, 1))); - value_multiply (k, k, val); - value_clear (val); + if (c) + { + Value val; + gcc_assert (host_integerp (TREE_OPERAND (e, 1), 0)); + value_init (val); + value_set_si (val, int_cst_value (TREE_OPERAND (e, 1))); + value_multiply (k, k, val); + value_clear (val); + } scan_tree_for_params (s, TREE_OPERAND (e, 0), c, r, k, subtract); } else { - Value val; - - gcc_assert (host_integerp (TREE_OPERAND (e, 0), 0)); - - value_init (val); - value_set_si (val, int_cst_value (TREE_OPERAND (e, 0))); - value_multiply (k, k, val); - value_clear (val); + if (c) + { + Value val; + gcc_assert (host_integerp (TREE_OPERAND (e, 0), 0)); + value_init (val); + value_set_si (val, int_cst_value (TREE_OPERAND (e, 0))); + value_multiply (k, k, val); + value_clear (val); + } scan_tree_for_params (s, TREE_OPERAND (e, 1), c, r, k, subtract); } break; @@ -2348,58 +2582,43 @@ idx_record_params (tree base, tree *idx, void *dta) access functions, conditions and loop bounds. */ static void -find_params_in_bb (scop_p scop, basic_block bb) +find_params_in_bb (scop_p scop, graphite_bb_p gb) { int i; data_reference_p dr; - VEC (data_reference_p, heap) *drs; - gimple_stmt_iterator gsi; - struct loop *nest = outermost_loop_in_scop (scop, bb); - - /* Find the parameters used in the memory access functions. */ - drs = VEC_alloc (data_reference_p, heap, 5); - for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) - find_data_references_in_stmt (nest, gsi_stmt (gsi), &drs); + gimple stmt; + loop_p father = GBB_BB (gb)->loop_father; - for (i = 0; VEC_iterate (data_reference_p, drs, i, dr); i++) + for (i = 0; VEC_iterate (data_reference_p, GBB_DATA_REFS (gb), i, dr); i++) { struct irp_data irp; - irp.loop = bb->loop_father; + irp.loop = father; irp.scop = scop; for_each_index (&dr->ref, idx_record_params, &irp); - free_data_ref (dr); } - VEC_free (data_reference_p, heap, drs); - /* Find parameters in conditional statements. */ - gsi = gsi_last_bb (bb); - if (!gsi_end_p (gsi)) + for (i = 0; VEC_iterate (gimple, GBB_CONDITIONS (gb), i, stmt); i++) { - gimple stmt = gsi_stmt (gsi); + Value one; + loop_p loop = father; - if (gimple_code (stmt) == GIMPLE_COND) - { - Value one; - loop_p loop = bb->loop_father; - - tree lhs, rhs; - - lhs = gimple_cond_lhs (stmt); - lhs = analyze_scalar_evolution (loop, lhs); - lhs = instantiate_scev (block_before_scop (scop), loop, lhs); - - rhs = gimple_cond_rhs (stmt); - rhs = analyze_scalar_evolution (loop, rhs); - rhs = instantiate_scev (block_before_scop (scop), loop, rhs); - - value_init (one); - scan_tree_for_params (scop, lhs, NULL, 0, one, false); - value_set_si (one, 1); - scan_tree_for_params (scop, rhs, NULL, 0, one, false); - value_clear (one); - } + tree lhs, rhs; + + lhs = gimple_cond_lhs (stmt); + lhs = analyze_scalar_evolution (loop, lhs); + lhs = instantiate_scev (block_before_scop (scop), loop, lhs); + + rhs = gimple_cond_rhs (stmt); + rhs = analyze_scalar_evolution (loop, rhs); + rhs = instantiate_scev (block_before_scop (scop), loop, rhs); + + value_init (one); + scan_tree_for_params (scop, lhs, NULL, 0, one, false); + value_set_si (one, 1); + scan_tree_for_params (scop, rhs, NULL, 0, one, false); + value_clear (one); } } @@ -2523,7 +2742,9 @@ find_scop_parameters (scop_p scop) /* Find the parameters used in data accesses. */ for (i = 0; VEC_iterate (graphite_bb_p, SCOP_BBS (scop), i, gb); i++) - find_params_in_bb (scop, GBB_BB (gb)); + find_params_in_bb (scop, gb); + + SCOP_ADD_PARAMS (scop) = false; } /* Build the context constraints for SCOP: constraints and relations @@ -2555,24 +2776,6 @@ gbb_from_bb (basic_block bb) return (graphite_bb_p) bb->aux; } -/* Add DOMAIN to all the basic blocks in LOOP. */ - -static void -add_bb_domains (struct loop *loop, CloogMatrix *domain) -{ - basic_block *bbs = get_loop_body (loop); - unsigned i; - - for (i = 0; i < loop->num_nodes; i++) - if (bbs[i]->loop_father == loop) - { - graphite_bb_p gbb = gbb_from_bb (bbs[i]); - GBB_DOMAIN (gbb) = cloog_matrix_copy (domain); - } - - free (bbs); -} - /* Builds the constraint matrix for LOOP in SCOP. NB_OUTER_LOOPS is the number of loops surrounding LOOP in SCOP. OUTER_CSTR gives the constraints matrix for the surrounding loops. */ @@ -2583,6 +2786,7 @@ build_loop_iteration_domains (scop_p scop, struct loop *loop, { int i, j, row; CloogMatrix *cstr; + graphite_bb_p gb; int nb_rows = outer_cstr->NbRows + 1; int nb_cols = outer_cstr->NbColumns + 1; @@ -2663,7 +2867,9 @@ build_loop_iteration_domains (scop_p scop, struct loop *loop, if (nb_outer_loops != 0 && loop->next && loop_in_scop_p (loop->next, scop)) build_loop_iteration_domains (scop, loop->next, outer_cstr, nb_outer_loops); - add_bb_domains (loop, cstr); + for (i = 0; VEC_iterate (graphite_bb_p, SCOP_BBS (scop), i, gb); i++) + if (gbb_loop (gb) == loop) + GBB_DOMAIN (gb) = cloog_matrix_copy (cstr); cloog_matrix_free (cstr); } @@ -2885,10 +3091,12 @@ build_scop_conditions_1 (VEC (gimple, heap) **conditions, /* Record conditions in graphite_bb. */ gbb = gbb_from_bb (bb); - GBB_CONDITIONS (gbb) = VEC_copy (gimple, heap, *conditions); - GBB_CONDITION_CASES (gbb) = VEC_copy (gimple, heap, *cases); - - add_conditions_to_domain (gbb); + if (gbb) + { + GBB_CONDITIONS (gbb) = VEC_copy (gimple, heap, *conditions); + GBB_CONDITION_CASES (gbb) = VEC_copy (gimple, heap, *cases); + add_conditions_to_domain (gbb); + } dom = get_dominated_by (CDI_DOMINATORS, bb); @@ -3050,27 +3258,31 @@ build_scop_iteration_domain (scop_p scop) } /* Initializes an equation CY of the access matrix using the - information for a subscript from ACCESS_FUN, relatively to the loop + information for a subscript from AF, relatively to the loop indexes from LOOP_NEST and parameter indexes from PARAMS. NDIM is the dimension of the array access, i.e. the number of subscripts. Returns true when the operation succeeds. */ static bool -build_access_matrix_with_af (tree access_fun, lambda_vector cy, +build_access_matrix_with_af (tree af, lambda_vector cy, scop_p scop, int ndim) { - switch (TREE_CODE (access_fun)) + int param_col; + + switch (TREE_CODE (af)) { case POLYNOMIAL_CHREC: { - tree left = CHREC_LEFT (access_fun); - tree right = CHREC_RIGHT (access_fun); + struct loop *outer_loop; + tree left = CHREC_LEFT (af); + tree right = CHREC_RIGHT (af); int var; if (TREE_CODE (right) != INTEGER_CST) return false; - - var = loop_iteration_vector_dim (CHREC_VARIABLE (access_fun), scop); + + outer_loop = get_loop (CHREC_VARIABLE (af)); + var = nb_loops_around_loop_in_scop (outer_loop, scop); cy[var] = int_cst_value (right); switch (TREE_CODE (left)) @@ -3083,12 +3295,27 @@ build_access_matrix_with_af (tree access_fun, lambda_vector cy, return true; default: - /* FIXME: access_fn can have parameters. */ - return false; + return build_access_matrix_with_af (left, cy, scop, ndim); } } + + case PLUS_EXPR: + build_access_matrix_with_af (TREE_OPERAND (af, 0), cy, scop, ndim); + build_access_matrix_with_af (TREE_OPERAND (af, 1), cy, scop, ndim); + return true; + + case MINUS_EXPR: + build_access_matrix_with_af (TREE_OPERAND (af, 0), cy, scop, ndim); + build_access_matrix_with_af (TREE_OPERAND (af, 1), cy, scop, ndim); + return true; + case INTEGER_CST: - cy[ndim - 1] = int_cst_value (access_fun); + cy[ndim - 1] = int_cst_value (af); + return true; + + case SSA_NAME: + param_col = param_index (af, scop); + cy [ndim - scop_nb_params (scop) + param_col - 1] = 1; return true; default: @@ -3134,23 +3361,14 @@ build_scop_data_accesses (scop_p scop) int i; graphite_bb_p gb; + /* FIXME: Construction of access matrix is disabled until some + pass, like the data dependence analysis, is using it. */ + return; + for (i = 0; VEC_iterate (graphite_bb_p, SCOP_BBS (scop), i, gb); i++) { int j; - gimple_stmt_iterator gsi; data_reference_p dr; - struct loop *nest = outermost_loop_in_scop (scop, GBB_BB (gb)); - - /* On each statement of the basic block, gather all the occurences - to read/write memory. */ - GBB_DATA_REFS (gb) = VEC_alloc (data_reference_p, heap, 5); - for (gsi = gsi_start_bb (GBB_BB (gb)); !gsi_end_p (gsi); gsi_next (&gsi)) - find_data_references_in_stmt (nest, gsi_stmt (gsi), - &GBB_DATA_REFS (gb)); - - /* FIXME: Construction of access matrix is disabled until some - pass, like the data dependence analysis, is using it. */ - continue; /* Construct the access matrix for each data ref, with respect to the loop nest of the current BB in the considered SCOP. */ @@ -3189,9 +3407,10 @@ clast_name_to_gcc (const char *name, VEC (name_tree, heap) *params, name_tree t; tree iv; - for (i = 0; VEC_iterate (name_tree, params, i, t); i++) - if (!strcmp (name, t->name)) - return t->t; + if (params) + for (i = 0; VEC_iterate (name_tree, params, i, t); i++) + if (!strcmp (name, t->name)) + return t->t; iv = loop_iv_stack_get_iv_from_name (ivstack, name); if (iv) @@ -3200,17 +3419,24 @@ clast_name_to_gcc (const char *name, VEC (name_tree, heap) *params, gcc_unreachable (); } -/* Converts a Cloog AST expression E back to a GCC expression tree. */ +/* Returns the maximal precision type for expressions E1 and E2. */ + +static inline tree +max_precision_type (tree e1, tree e2) +{ + tree type1 = TREE_TYPE (e1); + tree type2 = TREE_TYPE (e2); + return TYPE_PRECISION (type1) > TYPE_PRECISION (type2) ? type1 : type2; +} + +/* Converts a Cloog AST expression E back to a GCC expression tree + of type TYPE. */ static tree -clast_to_gcc_expression (struct clast_expr *e, +clast_to_gcc_expression (tree type, struct clast_expr *e, VEC (name_tree, heap) *params, loop_iv_stack ivstack) { - tree type = integer_type_node; - - gcc_assert (e); - switch (e->type) { case expr_term: @@ -3220,53 +3446,62 @@ clast_to_gcc_expression (struct clast_expr *e, if (t->var) { if (value_one_p (t->val)) - return clast_name_to_gcc (t->var, params, ivstack); + { + tree name = clast_name_to_gcc (t->var, params, ivstack); + return fold_convert (type, name); + } else if (value_mone_p (t->val)) - return fold_build1 (NEGATE_EXPR, type, - clast_name_to_gcc (t->var, params, ivstack)); + { + tree name = clast_name_to_gcc (t->var, params, ivstack); + name = fold_convert (type, name); + return fold_build1 (NEGATE_EXPR, type, name); + } else - return fold_build2 (MULT_EXPR, type, - gmp_cst_to_tree (t->val), - clast_name_to_gcc (t->var, params, ivstack)); + { + tree name = clast_name_to_gcc (t->var, params, ivstack); + tree cst = gmp_cst_to_tree (type, t->val); + name = fold_convert (type, name); + return fold_build2 (MULT_EXPR, type, cst, name); + } } else - return gmp_cst_to_tree (t->val); + return gmp_cst_to_tree (type, t->val); } case expr_red: { struct clast_reduction *r = (struct clast_reduction *) e; - tree left, right; switch (r->type) { case clast_red_sum: if (r->n == 1) - return clast_to_gcc_expression (r->elts[0], params, ivstack); + return clast_to_gcc_expression (type, r->elts[0], params, ivstack); else { + tree tl = clast_to_gcc_expression (type, r->elts[0], params, ivstack); + tree tr = clast_to_gcc_expression (type, r->elts[1], params, ivstack); + gcc_assert (r->n >= 1 && r->elts[0]->type == expr_term && r->elts[1]->type == expr_term); - left = clast_to_gcc_expression (r->elts[0], params, ivstack); - right = clast_to_gcc_expression (r->elts[1], params, ivstack); - return fold_build2 (PLUS_EXPR, type, left, right); + return fold_build2 (PLUS_EXPR, type, tl, tr); } break; case clast_red_min: if (r->n == 1) - return clast_to_gcc_expression (r->elts[0], params, ivstack); + return clast_to_gcc_expression (type, r->elts[0], params, ivstack); else if (r->n == 2) { - left = clast_to_gcc_expression (r->elts[0], params, ivstack); - right = clast_to_gcc_expression (r->elts[1], params, ivstack); - return fold_build2 (MIN_EXPR, type, left, right); + tree tl = clast_to_gcc_expression (type, r->elts[0], params, ivstack); + tree tr = clast_to_gcc_expression (type, r->elts[1], params, ivstack); + return fold_build2 (MIN_EXPR, type, tl, tr); } else @@ -3276,13 +3511,13 @@ clast_to_gcc_expression (struct clast_expr *e, case clast_red_max: if (r->n == 1) - return clast_to_gcc_expression (r->elts[0], params, ivstack); + return clast_to_gcc_expression (type, r->elts[0], params, ivstack); else if (r->n == 2) { - left = clast_to_gcc_expression (r->elts[0], params, ivstack); - right = clast_to_gcc_expression (r->elts[1], params, ivstack); - return fold_build2 (MAX_EXPR, type, left, right); + tree tl = clast_to_gcc_expression (type, r->elts[0], params, ivstack); + tree tr = clast_to_gcc_expression (type, r->elts[1], params, ivstack); + return fold_build2 (MAX_EXPR, type, tl, tr); } else @@ -3300,15 +3535,8 @@ clast_to_gcc_expression (struct clast_expr *e, { struct clast_binary *b = (struct clast_binary *) e; struct clast_expr *lhs = (struct clast_expr *) b->LHS; - struct clast_expr *rhs = (struct clast_expr *) b->RHS; - tree tl = clast_to_gcc_expression (lhs, params, ivstack); - - /* FIXME: The next statement produces a warning: Cloog assumes - that the RHS is a constant, but this is a "void *" pointer - that should be casted into a Value, but this cast cannot be - done as Value is a GMP type, that is an array. Cloog must - be fixed for removing this warning. */ - tree tr = gmp_cst_to_tree (rhs); + tree tl = clast_to_gcc_expression (type, lhs, params, ivstack); + tree tr = gmp_cst_to_tree (type, b->RHS); switch (b->type) { @@ -3336,6 +3564,72 @@ clast_to_gcc_expression (struct clast_expr *e, return NULL_TREE; } +/* Returns the type for the expression E. */ + +static tree +gcc_type_for_clast_expr (struct clast_expr *e, + VEC (name_tree, heap) *params, + loop_iv_stack ivstack) +{ + switch (e->type) + { + case expr_term: + { + struct clast_term *t = (struct clast_term *) e; + + if (t->var) + return TREE_TYPE (clast_name_to_gcc (t->var, params, ivstack)); + else + return NULL_TREE; + } + + case expr_red: + { + struct clast_reduction *r = (struct clast_reduction *) e; + + if (r->n == 1) + return gcc_type_for_clast_expr (r->elts[0], params, ivstack); + else + { + int i; + for (i = 0; i < r->n; i++) + { + tree type = gcc_type_for_clast_expr (r->elts[i], params, ivstack); + if (type) + return type; + } + return NULL_TREE; + } + } + + case expr_bin: + { + struct clast_binary *b = (struct clast_binary *) e; + struct clast_expr *lhs = (struct clast_expr *) b->LHS; + return gcc_type_for_clast_expr (lhs, params, ivstack); + } + + default: + gcc_unreachable (); + } + + return NULL_TREE; +} + +/* Returns the type for the equation CLEQ. */ + +static tree +gcc_type_for_clast_eq (struct clast_equation *cleq, + VEC (name_tree, heap) *params, + loop_iv_stack ivstack) +{ + tree type = gcc_type_for_clast_expr (cleq->LHS, params, ivstack); + if (type) + return type; + + return gcc_type_for_clast_expr (cleq->RHS, params, ivstack); +} + /* Translates a clast equation CLEQ to a tree. */ static tree @@ -3344,8 +3638,9 @@ graphite_translate_clast_equation (scop_p scop, loop_iv_stack ivstack) { enum tree_code comp; - tree lhs = clast_to_gcc_expression (cleq->LHS, SCOP_PARAMS (scop), ivstack); - tree rhs = clast_to_gcc_expression (cleq->RHS, SCOP_PARAMS (scop), ivstack); + tree type = gcc_type_for_clast_eq (cleq, SCOP_PARAMS (scop), ivstack); + tree lhs = clast_to_gcc_expression (type, cleq->LHS, SCOP_PARAMS (scop), ivstack); + tree rhs = clast_to_gcc_expression (type, cleq->RHS, SCOP_PARAMS (scop), ivstack); if (cleq->sign == 0) comp = EQ_EXPR; @@ -3356,7 +3651,7 @@ graphite_translate_clast_equation (scop_p scop, else comp = LE_EXPR; - return fold_build2 (comp, integer_type_node, lhs, rhs); + return fold_build2 (comp, type, lhs, rhs); } /* Creates the test for the condition in STMT. */ @@ -3373,7 +3668,7 @@ graphite_create_guard_cond_expr (scop_p scop, struct clast_guard *stmt, tree eq = graphite_translate_clast_equation (scop, &stmt->eq[i], ivstack); if (cond) - cond = fold_build2 (TRUTH_AND_EXPR, integer_type_node, cond, eq); + cond = fold_build2 (TRUTH_AND_EXPR, TREE_TYPE (eq), cond, eq); else cond = eq; } @@ -3393,6 +3688,41 @@ graphite_create_new_guard (scop_p scop, edge entry_edge, return exit_edge; } +/* Walks a CLAST and returns the first statement in the body of a + loop. */ + +static struct clast_user_stmt * +clast_get_body_of_loop (struct clast_stmt *stmt) +{ + if (!stmt + || CLAST_STMT_IS_A (stmt, stmt_user)) + return (struct clast_user_stmt *) stmt; + + if (CLAST_STMT_IS_A (stmt, stmt_for)) + return clast_get_body_of_loop (((struct clast_for *) stmt)->body); + + if (CLAST_STMT_IS_A (stmt, stmt_guard)) + return clast_get_body_of_loop (((struct clast_guard *) stmt)->then); + + if (CLAST_STMT_IS_A (stmt, stmt_block)) + return clast_get_body_of_loop (((struct clast_block *) stmt)->body); + + gcc_unreachable (); +} + +/* Returns the induction variable for the loop that gets translated to + STMT. */ + +static tree +gcc_type_for_iv_of_clast_loop (struct clast_for *stmt_for) +{ + struct clast_user_stmt *stmt = clast_get_body_of_loop ((struct clast_stmt *) stmt_for); + const char *cloog_iv = stmt_for->iterator; + CloogStatement *cs = stmt->statement; + graphite_bb_p gbb = (graphite_bb_p) cloog_statement_usr (cs); + + return gcc_type_for_cloog_iv (cloog_iv, gbb); +} /* Creates a new LOOP corresponding to Cloog's STMT. Inserts an induction variable for the new LOOP. New LOOP is attached to CFG starting at @@ -3404,63 +3734,114 @@ graphite_create_new_loop (scop_p scop, edge entry_edge, struct clast_for *stmt, loop_iv_stack ivstack, loop_p outer) { - struct loop *loop; - tree ivvar; - tree stride, lowb, upb; + tree type = gcc_type_for_iv_of_clast_loop (stmt); + VEC (name_tree, heap) *params = SCOP_PARAMS (scop); + tree lb = clast_to_gcc_expression (type, stmt->LB, params, ivstack); + tree ub = clast_to_gcc_expression (type, stmt->UB, params, ivstack); + tree stride = gmp_cst_to_tree (type, stmt->stride); + tree ivvar = create_tmp_var (type, "graphiteIV"); tree iv_before; + loop_p loop = create_empty_loop_on_edge + (entry_edge, lb, stride, ub, ivvar, &iv_before, + outer ? outer : entry_edge->src->loop_father); - gcc_assert (stmt->LB - && stmt->UB); - - stride = gmp_cst_to_tree (stmt->stride); - lowb = clast_to_gcc_expression (stmt->LB, SCOP_PARAMS (scop), ivstack); - ivvar = create_tmp_var (integer_type_node, "graphiteIV"); add_referenced_var (ivvar); - - upb = clast_to_gcc_expression (stmt->UB, SCOP_PARAMS (scop), ivstack); - loop = create_empty_loop_on_edge (entry_edge, lowb, stride, upb, ivvar, - &iv_before, outer ? outer - : entry_edge->src->loop_father); - loop_iv_stack_push_iv (ivstack, iv_before, stmt->iterator); - return loop; } -/* Remove all the edges from EDGES except the edge KEEP. */ +/* Structure containing the mapping between the old names and the new + names used after block copy in the new loop context. */ +typedef struct rename_map_elt +{ + tree old_name, new_name; +} *rename_map_elt; + + +/* Print to stderr the element ELT. */ static void -remove_all_edges_1 (VEC (edge, gc) *edges, edge keep) +debug_rename_elt (rename_map_elt elt) { - edge e; - edge_iterator ei; + fprintf (stderr, "("); + print_generic_expr (stderr, elt->old_name, 0); + fprintf (stderr, ", "); + print_generic_expr (stderr, elt->new_name, 0); + fprintf (stderr, ")\n"); +} - for (ei = ei_start (edges); (e = ei_safe_edge (ei)); ) - { - if (e != keep) - { - remove_edge (e); - e = ei_safe_edge (ei); - } - else - ei_next (&ei); - } +/* Helper function for debug_rename_map. */ + +static int +debug_rename_map_1 (void **slot, void *s ATTRIBUTE_UNUSED) +{ + struct rename_map_elt *entry = (struct rename_map_elt *) *slot; + debug_rename_elt (entry); + return 1; } -/* Remove all the edges from BB except the edge KEEP. */ +/* Print to stderr all the elements of MAP. */ -static void -remove_all_edges (basic_block bb, edge keep) +void +debug_rename_map (htab_t map) +{ + htab_traverse (map, debug_rename_map_1, NULL); +} + +/* Constructs a new SCEV_INFO_STR structure for VAR and INSTANTIATED_BELOW. */ + +static inline rename_map_elt +new_rename_map_elt (tree old_name, tree new_name) +{ + rename_map_elt res; + + res = XNEW (struct rename_map_elt); + res->old_name = old_name; + res->new_name = new_name; + + return res; +} + +/* Computes a hash function for database element ELT. */ + +static hashval_t +rename_map_elt_info (const void *elt) +{ + return htab_hash_pointer (((const struct rename_map_elt *) elt)->old_name); +} + +/* Compares database elements E1 and E2. */ + +static int +eq_rename_map_elts (const void *e1, const void *e2) { - remove_all_edges_1 (bb->succs, keep); - remove_all_edges_1 (bb->preds, keep); + const struct rename_map_elt *elt1 = (const struct rename_map_elt *) e1; + const struct rename_map_elt *elt2 = (const struct rename_map_elt *) e2; + + return (elt1->old_name == elt2->old_name); +} + +/* Returns the new name associated to OLD_NAME in MAP. */ + +static tree +get_new_name_from_old_name (htab_t map, tree old_name) +{ + struct rename_map_elt tmp; + PTR *slot; + + tmp.old_name = old_name; + slot = htab_find_slot (map, &tmp, NO_INSERT); + + if (slot && *slot) + return ((rename_map_elt) *slot)->new_name; + + return old_name; } /* Rename the SSA_NAMEs used in STMT and that appear in IVSTACK. */ static void -graphite_rename_ivs_stmt (gimple stmt, graphite_bb_p gbb, scop_p scop, - loop_p old, loop_iv_stack ivstack) +rename_variables_in_stmt (gimple stmt, htab_t map) { ssa_op_iter iter; use_operand_p use_p; @@ -3468,16 +3849,12 @@ graphite_rename_ivs_stmt (gimple stmt, graphite_bb_p gbb, scop_p scop, FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE) { tree use = USE_FROM_PTR (use_p); - tree new_iv = NULL; - name_tree old_iv = get_old_iv_from_ssa_name (scop, old, use); - - if (old_iv) - new_iv = loop_iv_stack_get_iv (ivstack, - gbb_loop_index (gbb, old_iv->loop)); + tree new_name = get_new_name_from_old_name (map, use); - if (new_iv) - SET_USE (use_p, new_iv); + replace_exp (use_p, new_name); } + + update_stmt (stmt); } /* Returns true if SSA_NAME is a parameter of SCOP. */ @@ -3496,28 +3873,26 @@ is_parameter (scop_p scop, tree ssa_name) return false; } -/* Returns true if NAME is an old induction variable in SCOP. OLD is - the original loop that contained the definition of NAME. */ +/* Returns true if NAME is an induction variable. */ static bool -is_old_iv (scop_p scop, loop_p old, tree name) +is_iv (tree name) { - return get_old_iv_from_ssa_name (scop, old, name) != NULL; - + return gimple_code (SSA_NAME_DEF_STMT (name)) == GIMPLE_PHI; } -static void expand_scalar_variables_stmt (gimple, graphite_bb_p, scop_p, loop_p, - loop_iv_stack); +static void expand_scalar_variables_stmt (gimple, basic_block, scop_p, + loop_p, htab_t); /* Constructs a tree which only contains old_ivs and parameters. Any - other variables that are defined outside GBB will be eliminated by + other variables that are defined outside BB will be eliminated by using their definitions in the constructed tree. OLD_LOOP_FATHER - is the original loop that contained GBB. */ + is the original loop that contained BB. */ static tree expand_scalar_variables_expr (tree type, tree op0, enum tree_code code, - tree op1, graphite_bb_p gbb, scop_p scop, - loop_p old_loop_father, loop_iv_stack ivstack) + tree op1, basic_block bb, scop_p scop, + loop_p old_loop_father, htab_t map) { if ((TREE_CODE_CLASS (code) == tcc_constant && code == INTEGER_CST) @@ -3530,8 +3905,7 @@ expand_scalar_variables_expr (tree type, tree op0, enum tree_code code, enum tree_code op0_code = TREE_CODE (op0); tree op0_expr = expand_scalar_variables_expr (op0_type, op0, op0_code, - NULL, gbb, scop, old_loop_father, - ivstack); + NULL, bb, scop, old_loop_father, map); return fold_build1 (code, type, op0_expr); } @@ -3542,14 +3916,12 @@ expand_scalar_variables_expr (tree type, tree op0, enum tree_code code, enum tree_code op0_code = TREE_CODE (op0); tree op0_expr = expand_scalar_variables_expr (op0_type, op0, op0_code, - NULL, gbb, scop, old_loop_father, - ivstack); + NULL, bb, scop, old_loop_father, map); tree op1_type = TREE_TYPE (op1); enum tree_code op1_code = TREE_CODE (op1); tree op1_expr = expand_scalar_variables_expr (op1_type, op1, op1_code, - NULL, gbb, scop, old_loop_father, - ivstack); + NULL, bb, scop, old_loop_father, map); return fold_build2 (code, type, op0_expr, op1_expr); } @@ -3560,34 +3932,34 @@ expand_scalar_variables_expr (tree type, tree op0, enum tree_code code, gimple def_stmt; enum tree_code subcode; - if(is_parameter (scop, op0) || - is_old_iv (scop, old_loop_father, op0)) - return op0; + if (is_parameter (scop, op0) + || is_iv (op0)) + return get_new_name_from_old_name (map, op0); def_stmt = SSA_NAME_DEF_STMT (op0); - if (gimple_bb (def_stmt) == GBB_BB (gbb)) + if (gimple_bb (def_stmt) == bb) { /* If the defining statement is in the basic block already we do not need to create a new expression for it, we only need to ensure its operands are expanded. */ - expand_scalar_variables_stmt (def_stmt, gbb, scop, - old_loop_father, ivstack); - return op0; + expand_scalar_variables_stmt (def_stmt, bb, scop, + old_loop_father, map); + return get_new_name_from_old_name (map, op0); } else { - if (gimple_code (def_stmt) != GIMPLE_ASSIGN) - return op0; + if (gimple_code (def_stmt) != GIMPLE_ASSIGN + || !bb_in_scop_p (gimple_bb (def_stmt), scop)) + return get_new_name_from_old_name (map, op0); var0 = gimple_assign_rhs1 (def_stmt); subcode = gimple_assign_rhs_code (def_stmt); var1 = gimple_assign_rhs2 (def_stmt); - return expand_scalar_variables_expr (type, var0, subcode, var1, - gbb, scop, old_loop_father, - ivstack); + return expand_scalar_variables_expr (type, var0, subcode, var1, + bb, scop, old_loop_father, map); } } @@ -3596,106 +3968,96 @@ expand_scalar_variables_expr (tree type, tree op0, enum tree_code code, } /* Replicates any uses of non-parameters and non-old-ivs variablesthat - are defind outside GBB with code that is inserted in GBB. + are defind outside BB with code that is inserted in BB. OLD_LOOP_FATHER is the original loop that contained STMT. */ static void -expand_scalar_variables_stmt (gimple stmt, graphite_bb_p gbb, scop_p scop, - loop_p old_loop_father, loop_iv_stack ivstack) +expand_scalar_variables_stmt (gimple stmt, basic_block bb, scop_p scop, + loop_p old_loop_father, htab_t map) { ssa_op_iter iter; use_operand_p use_p; - basic_block bb = GBB_BB (gbb); FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE) { tree use = USE_FROM_PTR (use_p); tree type = TREE_TYPE (use); enum tree_code code = TREE_CODE (use); - tree use_expr = expand_scalar_variables_expr (type, use, code, NULL, - gbb, scop, old_loop_father, - ivstack); + tree use_expr = expand_scalar_variables_expr (type, use, code, NULL, bb, + scop, old_loop_father, map); if (use_expr != use) { gimple_stmt_iterator gsi = gsi_after_labels (bb); tree new_use = force_gimple_operand_gsi (&gsi, use_expr, true, NULL, true, GSI_NEW_STMT); - SET_USE (use_p, new_use); + replace_exp (use_p, new_use); } } + + update_stmt (stmt); } -/* Copies the definitions outside of GBB of variables that are not - induction variables nor parameters. GBB must only contain +/* Copies the definitions outside of BB of variables that are not + induction variables nor parameters. BB must only contain "external" references to these types of variables. OLD_LOOP_FATHER - is the original loop that contained GBB. */ + is the original loop that contained BB. */ static void -expand_scalar_variables (graphite_bb_p gbb, scop_p scop, - loop_p old_loop_father, loop_iv_stack ivstack) +expand_scalar_variables (basic_block bb, scop_p scop, + loop_p old_loop_father, htab_t map) { - basic_block bb = GBB_BB (gbb); gimple_stmt_iterator gsi; for (gsi = gsi_after_labels (bb); !gsi_end_p (gsi);) { gimple stmt = gsi_stmt (gsi); - expand_scalar_variables_stmt (stmt, gbb, scop, old_loop_father, - ivstack); + expand_scalar_variables_stmt (stmt, bb, scop, old_loop_father, map); gsi_next (&gsi); } } -/* Rename all the SSA_NAMEs from block GBB that appear in IVSTACK in - terms of new induction variables. OLD_LOOP_FATHER is the original - loop that contained GBB. */ +/* Rename all the SSA_NAMEs from block BB according to the MAP. */ static void -graphite_rename_ivs (graphite_bb_p gbb, scop_p scop, loop_p old_loop_father, - loop_iv_stack ivstack) +rename_variables (basic_block bb, htab_t map) { - basic_block bb = GBB_BB (gbb); gimple_stmt_iterator gsi; - for (gsi = gsi_after_labels (bb); !gsi_end_p (gsi);) - { - gimple stmt = gsi_stmt (gsi); + for (gsi = gsi_after_labels (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + rename_variables_in_stmt (gsi_stmt (gsi), map); +} - if (gimple_get_lhs (stmt) - && TREE_CODE (gimple_get_lhs (stmt)) == SSA_NAME - && get_old_iv_from_ssa_name (scop, old_loop_father, - gimple_get_lhs (stmt))) - gsi_remove (&gsi, false); - else - { - graphite_rename_ivs_stmt (stmt, gbb, scop, old_loop_father, ivstack); - gsi_next (&gsi); - } - } +/* Rename following the information from MAP the PHI node argument + corresponding to the edge E. In order to allow several renames of + that argument, we match the original SSA_NAME on the argument + coming from the edge different than E. */ + +static void +rename_variables_from_edge (edge e, gimple phi, htab_t map) +{ + int n = e->dest_idx == 0 ? 1 : 0; + tree old_name = gimple_phi_arg_def (phi, n); + tree new_name = get_new_name_from_old_name (map, old_name); + + gcc_assert (gimple_phi_num_args (phi) == 2 + && gimple_phi_arg_edge (phi, e->dest_idx) == e); + + SET_PHI_ARG_DEF (phi, n, new_name); } -/* Move all the PHI nodes from block FROM to block TO. - OLD_LOOP_FATHER is the original loop that contained FROM. */ +/* Rename all the phi arguments for the edges comming from the scop + according to the MAP. */ static void -move_phi_nodes (scop_p scop, loop_p old_loop_father, basic_block from, - basic_block to) +rename_phis_end_scop (scop_p scop, htab_t map) { + basic_block after_scop = SCOP_EXIT (scop); + edge e = SESE_EXIT (SCOP_REGION (scop)); gimple_stmt_iterator gsi; - for (gsi = gsi_start_phis (from); !gsi_end_p (gsi);) - { - gimple phi = gsi_stmt (gsi); - tree op = gimple_phi_result (phi); - - if (get_old_iv_from_ssa_name (scop, old_loop_father, op) == NULL) - { - gimple new_phi = make_phi_node (op, 0); - add_phi_node_to_bb (new_phi, to); - } - remove_phi_node (&gsi, false); - } + for (gsi = gsi_start_phis (after_scop); !gsi_end_p (gsi); gsi_next (&gsi)) + rename_variables_from_edge (e, gsi_stmt (gsi), map); } /* Remove condition from BB. */ @@ -3728,6 +4090,132 @@ get_true_edge_from_guard_bb (basic_block bb) return NULL; } +/* Returns the first successor edge of BB with EDGE_TRUE_VALUE flag cleared. */ + +static edge +get_false_edge_from_guard_bb (basic_block bb) +{ + edge e; + edge_iterator ei; + + FOR_EACH_EDGE (e, ei, bb->succs) + if (!(e->flags & EDGE_TRUE_VALUE)) + return e; + + gcc_unreachable (); + return NULL; +} + +/* Inserts in MAP a tuple (OLD_NAME, NEW_NAME) for the induction + variables of the loops around GBB in SCOP, i.e. GBB_LOOPS. + NEW_NAME is obtained from IVSTACK. IVSTACK has the same stack + ordering as GBB_LOOPS. */ + +static void +build_iv_mapping (loop_iv_stack ivstack, htab_t map, gbb_p gbb, scop_p scop) +{ + int i; + name_tree iv; + PTR *slot; + + for (i = 0; VEC_iterate (name_tree, SCOP_OLDIVS (scop), i, iv); i++) + { + struct rename_map_elt tmp; + + if (!flow_bb_inside_loop_p (iv->loop, GBB_BB (gbb))) + continue; + + tmp.old_name = iv->t; + slot = htab_find_slot (map, &tmp, INSERT); + + if (!*slot) + { + tree new_name = loop_iv_stack_get_iv (ivstack, + gbb_loop_index (gbb, iv->loop)); + *slot = new_rename_map_elt (iv->t, new_name); + } + } +} + +/* Register in MAP the tuple (old_name, new_name). */ + +static void +register_old_new_names (htab_t map, tree old_name, tree new_name) +{ + struct rename_map_elt tmp; + PTR *slot; + + tmp.old_name = old_name; + slot = htab_find_slot (map, &tmp, INSERT); + + if (!*slot) + *slot = new_rename_map_elt (old_name, new_name); +} + +/* Create a duplicate of the basic block BB. NOTE: This does not + preserve SSA form. */ + +static void +graphite_copy_stmts_from_block (basic_block bb, basic_block new_bb, htab_t map) +{ + gimple_stmt_iterator gsi, gsi_tgt; + + gsi_tgt = gsi_start_bb (new_bb); + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + def_operand_p def_p; + ssa_op_iter op_iter; + int region; + gimple stmt = gsi_stmt (gsi); + gimple copy; + + if (gimple_code (stmt) == GIMPLE_LABEL) + continue; + + /* Create a new copy of STMT and duplicate STMT's virtual + operands. */ + copy = gimple_copy (stmt); + gsi_insert_after (&gsi_tgt, copy, GSI_NEW_STMT); + mark_symbols_for_renaming (copy); + + region = lookup_stmt_eh_region (stmt); + if (region >= 0) + add_stmt_to_eh_region (copy, region); + gimple_duplicate_stmt_histograms (cfun, copy, cfun, stmt); + + /* Create new names for all the definitions created by COPY and + add replacement mappings for each new name. */ + FOR_EACH_SSA_DEF_OPERAND (def_p, copy, op_iter, SSA_OP_DEF) + { + tree old_name = DEF_FROM_PTR (def_p); + tree new_name = create_new_def_for (old_name, copy, def_p); + register_old_new_names (map, old_name, new_name); + } + } +} + +/* Copies BB and includes in the copied BB all the statements that can + be reached following the use-def chains from the memory accesses, + and returns the next edge following this new block. */ + +static edge +copy_bb_and_scalar_dependences (basic_block bb, scop_p scop, + loop_p context_loop, + edge next_e, htab_t map) +{ + basic_block new_bb = split_edge (next_e); + + next_e = single_succ_edge (new_bb); + graphite_copy_stmts_from_block (bb, new_bb, map); + remove_condition (new_bb); + rename_variables (new_bb, map); + remove_phi_nodes (new_bb); + expand_scalar_variables (new_bb, scop, context_loop, map); + rename_phis_end_scop (scop, map); + + return next_e; +} + /* Translates a CLAST statement STMT to GCC representation. NEXT_E is the edge where new generated code should be attached. BB_EXIT is the last basic block that defines the scope of code generation. CONTEXT_LOOP is the @@ -3745,35 +4233,23 @@ translate_clast (scop_p scop, struct loop *context_loop, if (CLAST_STMT_IS_A (stmt, stmt_user)) { + htab_t map; CloogStatement *cs = ((struct clast_user_stmt *) stmt)->statement; graphite_bb_p gbb = (graphite_bb_p) cloog_statement_usr (cs); - basic_block bb = gbb->bb; - loop_p old_loop_father = bb->loop_father; - if (bb == ENTRY_BLOCK_PTR) + if (GBB_BB (gbb) == ENTRY_BLOCK_PTR) return next_e; - remove_condition (bb); - expand_scalar_variables (gbb, scop, old_loop_father, ivstack); - remove_all_edges (bb, next_e); - move_phi_nodes (scop, old_loop_father, bb, next_e->src); - redirect_edge_succ_nodup (next_e, bb); - - if (context_loop) - { - remove_bb_from_loops (bb); - add_bb_to_loop (bb, context_loop); - } - - set_immediate_dominator (CDI_DOMINATORS, next_e->dest, next_e->src); - mark_virtual_ops_in_bb (bb); - next_e = make_edge (bb, - context_loop ? context_loop->latch : EXIT_BLOCK_PTR, - EDGE_FALLTHRU); - loop_iv_stack_patch_for_consts (ivstack, - (struct clast_user_stmt *) stmt); - graphite_rename_ivs (gbb, scop, old_loop_father, ivstack); + map = htab_create (10, rename_map_elt_info, eq_rename_map_elts, free); + loop_iv_stack_patch_for_consts (ivstack, (struct clast_user_stmt *) stmt); + build_iv_mapping (ivstack, map, gbb, scop); + next_e = copy_bb_and_scalar_dependences (GBB_BB (gbb), scop, + context_loop, next_e, map); + htab_delete (map); loop_iv_stack_remove_constants (ivstack); + update_ssa (TODO_update_ssa); + recompute_all_dominators (); + graphite_verify (); return translate_clast (scop, context_loop, stmt->next, next_e, ivstack); } @@ -3791,7 +4267,9 @@ translate_clast (scop_p scop, struct loop *context_loop, set_immediate_dominator (CDI_DOMINATORS, next_e->dest, next_e->src); loop_iv_stack_pop (ivstack); - + last_e = single_succ_edge (split_edge (last_e)); + recompute_all_dominators (); + graphite_verify (); return translate_clast (scop, context_loop, stmt->next, last_e, ivstack); } @@ -3804,7 +4282,7 @@ translate_clast (scop_p scop, struct loop *context_loop, next_e = translate_clast (scop, context_loop, ((struct clast_guard *) stmt)->then, true_e, ivstack); - redirect_edge_succ_nodup (next_e, last_e->src); + graphite_verify (); return translate_clast (scop, context_loop, stmt->next, last_e, ivstack); } @@ -3813,6 +4291,7 @@ translate_clast (scop_p scop, struct loop *context_loop, next_e = translate_clast (scop, context_loop, ((struct clast_block *) stmt)->body, next_e, ivstack); + graphite_verify (); return translate_clast (scop, context_loop, stmt->next, next_e, ivstack); } @@ -4027,295 +4506,449 @@ find_transform (scop_p scop) return stmt; } -/* Return a vector of all the virtual phi nodes in the current - function. */ - -static VEC (gimple, heap) * -collect_virtual_phis (void) +/* Returns true when it is possible to generate code for this STMT. + For the moment we cannot generate code when Cloog decides to + duplicate a statement, as we do not do a copy, but a move. + USED_BASIC_BLOCKS records the blocks that have already been seen. + We return false if we have to generate code twice for the same + block. */ + +static bool +can_generate_code_stmt (struct clast_stmt *stmt, + struct pointer_set_t *used_basic_blocks) { - gimple_stmt_iterator si; - gimple_vec phis = VEC_alloc (gimple, heap, 3); - basic_block bb; + if (!stmt) + return true; - FOR_EACH_BB (bb) - for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si)) - /* The phis we moved will have 0 arguments because the - original edges were removed. */ - if (gimple_phi_num_args (gsi_stmt (si)) == 0) - VEC_safe_push (gimple, heap, phis, gsi_stmt (si)); + if (CLAST_STMT_IS_A (stmt, stmt_root)) + return can_generate_code_stmt (stmt->next, used_basic_blocks); - /* Deallocate if we did not find any. */ - if (VEC_length (gimple, phis) == 0) + if (CLAST_STMT_IS_A (stmt, stmt_user)) { - VEC_free (gimple, heap, phis); - phis = NULL; - } + CloogStatement *cs = ((struct clast_user_stmt *) stmt)->statement; + graphite_bb_p gbb = (graphite_bb_p) cloog_statement_usr (cs); - return phis; + if (pointer_set_contains (used_basic_blocks, gbb)) + return false; + pointer_set_insert (used_basic_blocks, gbb); + return can_generate_code_stmt (stmt->next, used_basic_blocks); + } + + if (CLAST_STMT_IS_A (stmt, stmt_for)) + return can_generate_code_stmt (((struct clast_for *) stmt)->body, + used_basic_blocks) + && can_generate_code_stmt (stmt->next, used_basic_blocks); + + if (CLAST_STMT_IS_A (stmt, stmt_guard)) + return can_generate_code_stmt (((struct clast_guard *) stmt)->then, + used_basic_blocks); + + if (CLAST_STMT_IS_A (stmt, stmt_block)) + return can_generate_code_stmt (((struct clast_block *) stmt)->body, + used_basic_blocks) + && can_generate_code_stmt (stmt->next, used_basic_blocks); + + return false; } -/* Find a virtual definition for variable VAR in BB. */ +/* Returns true when it is possible to generate code for this STMT. */ -static tree -find_vdef_for_var_in_bb (basic_block bb, tree var) +static bool +can_generate_code (struct clast_stmt *stmt) { - gimple_stmt_iterator gsi; - gimple phi; - def_operand_p def_var; - vuse_vec_p vv; - ssa_op_iter op_iter; - - for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi); gsi_prev (&gsi)) - FOR_EACH_SSA_VDEF_OPERAND (def_var, vv, gsi_stmt (gsi), op_iter) - if (SSA_NAME_VAR (*def_var) == var) - return *def_var; - - for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi); gsi_prev (&gsi)) - FOR_EACH_SSA_DEF_OPERAND (def_var, gsi_stmt (gsi), op_iter, SSA_OP_DEF) - if (SSA_NAME_VAR (*def_var) == var) - return *def_var; - - for (gsi = gsi_start_phis (bb); !gsi_end_p(gsi); gsi_next (&gsi)) - { - phi = gsi_stmt (gsi); - if (SSA_NAME_VAR (PHI_RESULT (phi)) == var) - return PHI_RESULT (phi); - } + bool result; + struct pointer_set_t *used_basic_blocks = pointer_set_create (); - return NULL; + result = can_generate_code_stmt (stmt, used_basic_blocks); + pointer_set_destroy (used_basic_blocks); + return result; } -/* Recursive helper. */ +/* Remove from the CFG the REGION. */ -static tree -find_vdef_for_var_1 (basic_block bb, struct pointer_set_t *visited, tree var) +static inline void +remove_sese_region (sese region) { - tree result = NULL; - edge_iterator ei; - edge pred_edge; - - if (pointer_set_contains (visited, bb)) - return NULL; + VEC (basic_block, heap) *bbs = NULL; + basic_block entry_bb = SESE_ENTRY (region)->dest; + basic_block exit_bb = SESE_EXIT (region)->dest; + basic_block bb; + int i; - pointer_set_insert (visited, bb); - result = find_vdef_for_var_in_bb (bb, var); + VEC_safe_push (basic_block, heap, bbs, entry_bb); + gather_blocks_in_sese_region (entry_bb, exit_bb, &bbs); - if (!result) - FOR_EACH_EDGE (pred_edge, ei, bb->preds) - if (!result) - result = find_vdef_for_var_1 (pred_edge->src, visited, var); + for (i = 0; VEC_iterate (basic_block, bbs, i, bb); i++) + delete_basic_block (bb); - return result; + VEC_free (basic_block, heap, bbs); } -/* Finds a virtual definition for variable VAR. */ +typedef struct ifsese { + sese region; + sese true_region; + sese false_region; +} *ifsese; -static tree -find_vdef_for_var (basic_block bb, tree var) +static inline edge +if_region_entry (ifsese if_region) { - struct pointer_set_t *visited = pointer_set_create (); - tree def = find_vdef_for_var_1 (bb, visited, var); + return SESE_ENTRY (if_region->region); +} - pointer_set_destroy (visited); - return def; +static inline edge +if_region_exit (ifsese if_region) +{ + return SESE_EXIT (if_region->region); } -/* Update the virtual phis after loop bodies are moved to new - loops. */ +static inline basic_block +if_region_get_condition_block (ifsese if_region) +{ + return if_region_entry (if_region)->dest; +} -static void -patch_phis_for_virtual_defs (void) +static inline void +if_region_set_false_region (ifsese if_region, sese region) { - int i; - gimple phi; - VEC (gimple, heap) *virtual_phis = collect_virtual_phis (); - - for (i = 0; VEC_iterate (gimple, virtual_phis, i, phi); i++) + basic_block condition = if_region_get_condition_block (if_region); + edge false_edge = get_false_edge_from_guard_bb (condition); + edge entry_region = SESE_ENTRY (region); + edge exit_region = SESE_EXIT (region); + basic_block before_region = entry_region->src; + basic_block last_in_region = exit_region->src; + void **slot = htab_find_slot_with_hash (current_loops->exits, exit_region, + htab_hash_pointer (exit_region), + NO_INSERT); + + entry_region->flags = false_edge->flags; + false_edge->flags = exit_region->flags; + + redirect_edge_pred (entry_region, condition); + redirect_edge_pred (exit_region, before_region); + redirect_edge_pred (false_edge, last_in_region); + + exit_region->flags = EDGE_FALLTHRU; + recompute_all_dominators (); + + SESE_EXIT (region) = single_succ_edge (false_edge->dest); + if_region->false_region = region; + + if (slot) { - basic_block bb = gimple_bb (phi); - edge_iterator ei; - edge pred_edge; - gimple_stmt_iterator gsi; - gimple new_phi; - tree phi_result = PHI_RESULT (phi); - tree var = SSA_NAME_VAR (phi_result); + struct loop_exit *loop_exit = GGC_CNEW (struct loop_exit); - new_phi = create_phi_node (phi_result, bb); - SSA_NAME_DEF_STMT (phi_result) = new_phi; + memcpy (loop_exit, *((struct loop_exit **) slot), sizeof (struct loop_exit)); + htab_clear_slot (current_loops->exits, slot); - FOR_EACH_EDGE (pred_edge, ei, bb->preds) - { - tree def = find_vdef_for_var (pred_edge->src, var); + slot = htab_find_slot_with_hash (current_loops->exits, false_edge, + htab_hash_pointer (false_edge), + INSERT); + loop_exit->e = false_edge; + *slot = loop_exit; + false_edge->src->loop_father->exits->next = loop_exit; + } +} - if (def) - add_phi_arg (new_phi, def, pred_edge); - else - add_phi_arg (new_phi, gimple_default_def (cfun, var), pred_edge); - } +static ifsese +create_if_region_on_edge (edge entry, tree condition) +{ + edge e; + edge_iterator ei; + sese sese_region = GGC_NEW (struct sese); + sese true_region = GGC_NEW (struct sese); + sese false_region = GGC_NEW (struct sese); + ifsese if_region = GGC_NEW (struct ifsese); + edge exit = create_empty_if_region_on_edge (entry, condition); - gsi = gsi_for_stmt (phi); - remove_phi_node (&gsi, false); + if_region->region = sese_region; + if_region->region->entry = entry; + if_region->region->exit = exit; + + FOR_EACH_EDGE (e, ei, entry->dest->succs) + { + if (e->flags & EDGE_TRUE_VALUE) + { + true_region->entry = e; + true_region->exit = single_succ_edge (e->dest); + if_region->true_region = true_region; + } + else if (e->flags & EDGE_FALSE_VALUE) + { + false_region->entry = e; + false_region->exit = single_succ_edge (e->dest); + if_region->false_region = false_region; + } } - VEC_free (gimple, heap, virtual_phis); + return if_region; } -/* Mark the original loops of SCOP for removal, replacing their header - field with NULL. */ +/* Moves REGION in a condition expression: + | if (1) + | ; + | else + | REGION; +*/ -static void -mark_old_loops (scop_p scop) +static ifsese +move_sese_in_condition (sese region) { - int i; - struct loop *loop; + basic_block pred_block = split_edge (SESE_ENTRY (region)); + ifsese if_region = NULL; - for (i = 0; VEC_iterate (loop_p, SCOP_LOOP_NEST (scop), i, loop); i++) - { - loop->header = NULL; - loop->latch = NULL; - } + SESE_ENTRY (region) = single_succ_edge (pred_block); + if_region = create_if_region_on_edge (single_pred_edge (pred_block), integer_one_node); + if_region_set_false_region (if_region, region); + + return if_region; +} + +/* Returns true when BB is in REGION. */ + +static bool +bb_in_sese_p (basic_block bb, sese region) +{ + return pointer_set_contains (SESE_REGION_BBS (region), bb); } -/* Scan the loops and remove the ones that have been marked for - removal. */ +/* For USE in BB, if it is used outside of the REGION it is defined in, + mark it for rewrite. Record basic block BB where it is used + to USE_BLOCKS. Record the ssa name index to NEED_PHIS bitmap. */ static void -remove_dead_loops (void) +sese_find_uses_to_rename_use (sese region, basic_block bb, tree use, + bitmap *use_blocks, bitmap need_phis) { - struct loop *loop, *ploop; - loop_iterator li; + unsigned ver; + basic_block def_bb; - FOR_EACH_LOOP (li, loop, LI_FROM_INNERMOST) - { - /* Remove only those loops that we marked to be removed with - mark_old_loops. */ - if (loop->header) - continue; + if (TREE_CODE (use) != SSA_NAME) + return; - while (loop->inner) - { - ploop = loop->inner; - flow_loop_tree_node_remove (ploop); - flow_loop_tree_node_add (loop_outer (loop), ploop); - } + ver = SSA_NAME_VERSION (use); + def_bb = gimple_bb (SSA_NAME_DEF_STMT (use)); + if (!def_bb + || !bb_in_sese_p (def_bb, region) + || bb_in_sese_p (bb, region)) + return; - /* Remove the loop and free its data. */ - delete_loop (loop); - } + if (!use_blocks[ver]) + use_blocks[ver] = BITMAP_ALLOC (NULL); + bitmap_set_bit (use_blocks[ver], bb->index); + + bitmap_set_bit (need_phis, ver); } -/* Returns true when it is possible to generate code for this STMT. - For the moment we cannot generate code when Cloog decides to - duplicate a statement, as we do not do a copy, but a move. - USED_BASIC_BLOCKS records the blocks that have already been seen. - We return false if we have to generate code twice for the same - block. */ +/* Marks names that are used in BB and outside of the loop they are + defined in for rewrite. Records the set of blocks in that the ssa + names are defined to USE_BLOCKS. Record the SSA names that will + need exit PHIs in NEED_PHIS. */ -static bool -can_generate_code_stmt (struct clast_stmt *stmt, - struct pointer_set_t *used_basic_blocks) +static void +sese_find_uses_to_rename_bb (sese region, basic_block bb, + bitmap *use_blocks, bitmap need_phis) { - if (!stmt) - return true; + gimple_stmt_iterator bsi; + edge e; + edge_iterator ei; + ssa_op_iter iter; + tree var; - if (CLAST_STMT_IS_A (stmt, stmt_root)) - return can_generate_code_stmt (stmt->next, used_basic_blocks); + FOR_EACH_EDGE (e, ei, bb->succs) + for (bsi = gsi_start_phis (e->dest); !gsi_end_p (bsi); gsi_next (&bsi)) + sese_find_uses_to_rename_use (region, bb, + PHI_ARG_DEF_FROM_EDGE (gsi_stmt (bsi), e), + use_blocks, need_phis); - if (CLAST_STMT_IS_A (stmt, stmt_user)) - { - CloogStatement *cs = ((struct clast_user_stmt *) stmt)->statement; - graphite_bb_p gbb = (graphite_bb_p) cloog_statement_usr (cs); + for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi)) + FOR_EACH_SSA_TREE_OPERAND (var, gsi_stmt (bsi), iter, SSA_OP_ALL_USES) + sese_find_uses_to_rename_use (region, bb, var, use_blocks, need_phis); +} - if (pointer_set_contains (used_basic_blocks, gbb)) - return false; - pointer_set_insert (used_basic_blocks, gbb); - return can_generate_code_stmt (stmt->next, used_basic_blocks); - } +/* Add exit phis for USE on EXIT. */ - if (CLAST_STMT_IS_A (stmt, stmt_for)) - return can_generate_code_stmt (((struct clast_for *) stmt)->body, - used_basic_blocks) - && can_generate_code_stmt (stmt->next, used_basic_blocks); +static void +sese_add_exit_phis_edge (basic_block exit, tree use, edge false_e, edge true_e) +{ + gimple phi = create_phi_node (use, exit); - if (CLAST_STMT_IS_A (stmt, stmt_guard)) - return can_generate_code_stmt (((struct clast_guard *) stmt)->then, - used_basic_blocks); + create_new_def_for (gimple_phi_result (phi), phi, + gimple_phi_result_ptr (phi)); + add_phi_arg (phi, use, false_e); + add_phi_arg (phi, use, true_e); +} - if (CLAST_STMT_IS_A (stmt, stmt_block)) - return can_generate_code_stmt (((struct clast_block *) stmt)->body, - used_basic_blocks) - && can_generate_code_stmt (stmt->next, used_basic_blocks); +/* Add phi nodes for VAR that is used in LIVEIN. Phi nodes are + inserted in block WHERE. */ - return false; +static void +sese_add_exit_phis_var (basic_block where, tree var, bitmap livein, + edge false_e, edge true_e) +{ + bitmap def; + basic_block def_bb = gimple_bb (SSA_NAME_DEF_STMT (var)); + + if (is_gimple_reg (var)) + bitmap_clear_bit (livein, def_bb->index); + else + bitmap_set_bit (livein, def_bb->index); + + def = BITMAP_ALLOC (NULL); + bitmap_set_bit (def, def_bb->index); + compute_global_livein (livein, def); + BITMAP_FREE (def); + + sese_add_exit_phis_edge (where, var, false_e, true_e); } -/* Returns true when it is possible to generate code for this STMT. */ +/* Insert in the block WHERE phi nodes for variables defined in REGION + and used outside the REGION. */ -static bool -can_generate_code (struct clast_stmt *stmt) +static void +rewrite_into_sese_closed_ssa (sese region, basic_block where, + edge false_e, edge true_e) { - bool result; - struct pointer_set_t *used_basic_blocks = pointer_set_create (); + unsigned i; + basic_block bb; + bitmap_iterator bi; + bitmap names_to_rename = BITMAP_ALLOC (NULL); + unsigned old_num_ssa_names = num_ssa_names; + bitmap *use_blocks = XCNEWVEC (bitmap, old_num_ssa_names); - result = can_generate_code_stmt (stmt, used_basic_blocks); - pointer_set_destroy (used_basic_blocks); - return result; + update_ssa (TODO_update_ssa); + + FOR_EACH_BB (bb) + sese_find_uses_to_rename_bb (region, bb, use_blocks, names_to_rename); + + EXECUTE_IF_SET_IN_BITMAP (names_to_rename, 0, i, bi) + sese_add_exit_phis_var (where, ssa_name (i), use_blocks[i], + false_e, true_e); + + update_ssa (TODO_update_ssa); + + for (i = 0; i < old_num_ssa_names; i++) + BITMAP_FREE (use_blocks[i]); + + free (use_blocks); + BITMAP_FREE (names_to_rename); } -/* Skip any definition that is a phi node with a single phi def. */ +/* Returns the first cloog name used in EXPR. */ -static tree -skip_phi_defs (tree ssa_name) +static const char * +find_cloog_iv_in_expr (struct clast_expr *expr) { - tree result = ssa_name; - gimple def_stmt = SSA_NAME_DEF_STMT (ssa_name); + struct clast_term *term = (struct clast_term *) expr; - if (gimple_code (def_stmt) == GIMPLE_PHI - && gimple_phi_num_args (def_stmt) == 1) - result = skip_phi_defs (gimple_phi_arg(def_stmt,0)->def); + if (expr->type == expr_term + && !term->var) + return NULL; - return result; + if (expr->type == expr_term) + return term->var; + + if (expr->type == expr_red) + { + int i; + struct clast_reduction *red = (struct clast_reduction *) expr; + + for (i = 0; i < red->n; i++) + { + const char *res = find_cloog_iv_in_expr ((red)->elts[i]); + + if (res) + return res; + } + } + + return NULL; } -/* Returns a VEC containing the phi-arg defs coming from SCOP_EXIT in - the destination block of SCOP_EXIT. */ +/* Build for a clast_user_stmt USER_STMT a map between the CLAST + induction variables and the corresponding GCC old induction + variables. This information is stored on each GRAPHITE_BB. */ -static VEC (tree, heap) * -collect_scop_exit_phi_args (edge scop_exit) +static void +compute_cloog_iv_types_1 (graphite_bb_p gbb, + struct clast_user_stmt *user_stmt) { - VEC (tree, heap) *phi_args = VEC_alloc (tree, heap, 1); - gimple_stmt_iterator gsi; + struct clast_stmt *t; + int index = 0; - for (gsi = gsi_start_phis (scop_exit->dest); !gsi_end_p (gsi); gsi_next (&gsi)) + for (t = user_stmt->substitutions; t; t = t->next, index++) { - gimple phi = gsi_stmt (gsi); - tree phi_arg = skip_phi_defs(PHI_ARG_DEF_FROM_EDGE (phi, scop_exit)); + PTR *slot; + struct ivtype_map_elt tmp; + struct clast_expr *expr = (struct clast_expr *) + ((struct clast_assignment *)t)->RHS; - VEC_safe_push (tree, heap, phi_args, phi_arg); - } + /* Create an entry (clast_var, type). */ + tmp.cloog_iv = find_cloog_iv_in_expr (expr); + if (!tmp.cloog_iv) + continue; + + slot = htab_find_slot (GBB_CLOOG_IV_TYPES (gbb), &tmp, INSERT); - return phi_args; + if (!*slot) + { + loop_p loop = gbb_loop_at_index (gbb, index); + tree oldiv = oldiv_for_loop (GBB_SCOP (gbb), loop); + tree type = oldiv ? TREE_TYPE (oldiv) : integer_type_node; + *slot = new_ivtype_map_elt (tmp.cloog_iv, type); + } + } } -/* Patches (adds) PHI_ARGS to the phi nodes in SCOP_EXIT destination. */ +/* Walk the CLAST tree starting from STMT and build for each + clast_user_stmt a map between the CLAST induction variables and the + corresponding GCC old induction variables. This information is + stored on each GRAPHITE_BB. */ static void -patch_scop_exit_phi_args (edge scop_exit, - VEC (tree, heap) *phi_args) +compute_cloog_iv_types (struct clast_stmt *stmt) { - int i = 0; - gimple_stmt_iterator gsi; + if (!stmt) + return; + + if (CLAST_STMT_IS_A (stmt, stmt_root)) + goto next; - for (gsi = gsi_start_phis (scop_exit->dest); !gsi_end_p (gsi); - gsi_next (&gsi), i++) + if (CLAST_STMT_IS_A (stmt, stmt_user)) { - tree def = VEC_index (tree, phi_args, i); - gimple phi = gsi_stmt (gsi); + CloogStatement *cs = ((struct clast_user_stmt *) stmt)->statement; + graphite_bb_p gbb = (graphite_bb_p) cloog_statement_usr (cs); + GBB_CLOOG_IV_TYPES (gbb) = htab_create (10, ivtype_map_elt_info, + eq_ivtype_map_elts, free); + compute_cloog_iv_types_1 (gbb, (struct clast_user_stmt *) stmt); + goto next; + } - gcc_assert (PHI_ARG_DEF_FROM_EDGE (phi, scop_exit) == NULL); + if (CLAST_STMT_IS_A (stmt, stmt_for)) + { + struct clast_stmt *s = ((struct clast_for *) stmt)->body; + compute_cloog_iv_types (s); + goto next; + } - add_phi_arg (phi, def, scop_exit); + if (CLAST_STMT_IS_A (stmt, stmt_guard)) + { + struct clast_stmt *s = ((struct clast_guard *) stmt)->then; + compute_cloog_iv_types (s); + goto next; } + + if (CLAST_STMT_IS_A (stmt, stmt_block)) + { + struct clast_stmt *s = ((struct clast_block *) stmt)->body; + compute_cloog_iv_types (s); + goto next; + } + + gcc_unreachable (); + + next: + compute_cloog_iv_types (stmt->next); } /* GIMPLE Loop Generator: generates loops from STMT in GIMPLE form for @@ -4325,14 +4958,10 @@ static void gloog (scop_p scop, struct clast_stmt *stmt) { edge new_scop_exit_edge = NULL; - basic_block scop_exit = SCOP_EXIT (scop); - VEC (tree, heap) *phi_args = - collect_scop_exit_phi_args (SESE_EXIT (SCOP_REGION (scop))); - VEC (iv_stack_entry_p, heap) *ivstack = - VEC_alloc (iv_stack_entry_p, heap, 10); - edge construction_edge = SESE_ENTRY (SCOP_REGION (scop)); - basic_block old_scop_exit_idom = get_immediate_dominator (CDI_DOMINATORS, - scop_exit); + VEC (iv_stack_entry_p, heap) *ivstack = VEC_alloc (iv_stack_entry_p, heap, + 10); + loop_p context_loop; + ifsese if_region = NULL; if (!can_generate_code (stmt)) { @@ -4340,39 +4969,23 @@ gloog (scop_p scop, struct clast_stmt *stmt) return; } - redirect_edge_succ_nodup (construction_edge, EXIT_BLOCK_PTR); - new_scop_exit_edge = translate_clast (scop, - construction_edge->src->loop_father, - stmt, construction_edge, &ivstack); + if_region = move_sese_in_condition (SCOP_REGION (scop)); + rewrite_into_sese_closed_ssa (SCOP_REGION (scop), + if_region->region->exit->src, + if_region->false_region->exit, + if_region->true_region->exit); + graphite_verify (); + context_loop = SESE_ENTRY (SCOP_REGION (scop))->src->loop_father; + compute_cloog_iv_types (stmt); + new_scop_exit_edge = translate_clast (scop, context_loop, + stmt, if_region->true_region->entry, + &ivstack); + graphite_verify (); + cleanup_tree_cfg (); + recompute_all_dominators (); + graphite_verify (); free_loop_iv_stack (&ivstack); - redirect_edge_succ (new_scop_exit_edge, scop_exit); - - if (!old_scop_exit_idom - || !dominated_by_p (CDI_DOMINATORS, SCOP_ENTRY (scop), - old_scop_exit_idom) - || SCOP_ENTRY (scop) == old_scop_exit_idom) - set_immediate_dominator (CDI_DOMINATORS, - new_scop_exit_edge->dest, - new_scop_exit_edge->src); - cloog_clast_free (stmt); - - if (new_scop_exit_edge->dest == EXIT_BLOCK_PTR) - new_scop_exit_edge->flags = 0; - - delete_unreachable_blocks (); - patch_phis_for_virtual_defs (); - patch_scop_exit_phi_args (new_scop_exit_edge, phi_args); - VEC_free (tree, heap, phi_args); - mark_old_loops (scop); - remove_dead_loops (); - rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa); - -#ifdef ENABLE_CHECKING - verify_loop_structure (); - verify_dominators (CDI_DOMINATORS); - verify_ssa (false); -#endif } /* Returns the number of data references in SCOP. */ @@ -4390,104 +5003,6 @@ nb_data_refs_in_scop (scop_p scop) return res; } -/* Check if a graphite bb can be ignored in graphite. We ignore all - bbs, that only contain code, that will be eliminated later. - - TODO: - Move PHI nodes and scalar variables out of these bbs, that only - remain conditions and induction variables. */ - -static bool -gbb_can_be_ignored (graphite_bb_p gb) -{ - gimple_stmt_iterator gsi; - scop_p scop = GBB_SCOP (gb); - loop_p loop = GBB_BB (gb)->loop_father; - - if (VEC_length (data_reference_p, GBB_DATA_REFS(gb))) - return false; - - /* Check statements. */ - for (gsi = gsi_start_bb (GBB_BB (gb)); !gsi_end_p (gsi); gsi_next (&gsi)) - { - gimple stmt = gsi_stmt (gsi); - switch (gimple_code (stmt)) - { - /* Control flow expressions can be ignored, as they are - represented in the iteration domains and will be - regenerated by graphite. */ - case GIMPLE_COND: - case GIMPLE_GOTO: - case GIMPLE_SWITCH: - break; - - /* Scalar variables can be ignored, if we can regenerate - them later using their scalar evolution function. - XXX: Just a heuristic, that needs further investigation. */ - case GIMPLE_ASSIGN: - { - tree var = gimple_assign_lhs (stmt); - var = analyze_scalar_evolution (loop, var); - var = instantiate_scev (block_before_scop (scop), loop, var); - - if (TREE_CODE (var) == SCEV_NOT_KNOWN) - return false; - - break; - } - /* Otherwise not ignoreable. */ - default: - return false; - } - } - - return true; -} - -/* Remove all ignoreable gbbs from SCOP. */ - -static void -scop_remove_ignoreable_gbbs (scop_p scop) -{ - graphite_bb_p gb; - int i; - - int max_schedule = scop_max_loop_depth (scop) + 1; - lambda_vector last_schedule = lambda_vector_new (max_schedule); - lambda_vector_clear (last_schedule, max_schedule); - - /* Update schedules. */ - for (i = 0; VEC_iterate (graphite_bb_p, SCOP_BBS (scop), i, gb); i++) - { - int nb_loops = gbb_nb_loops (gb); - - if (GBB_STATIC_SCHEDULE (gb) [nb_loops] == 0) - last_schedule [nb_loops] = 0; - - if (gbb_can_be_ignored (gb)) - { - /* Mark gbb for remove. */ - bitmap_clear_bit (SCOP_BBS_B (scop), gb->bb->index); - GBB_SCOP (gb) = NULL; - last_schedule [nb_loops]--; - } - else - lambda_vector_add (GBB_STATIC_SCHEDULE (gb), last_schedule, - GBB_STATIC_SCHEDULE (gb), nb_loops + 1); - } - - /* Remove gbbs. */ - for (i = 0; VEC_iterate (graphite_bb_p, SCOP_BBS (scop), i, gb); i++) - if (GBB_SCOP (gb) == NULL) - { - VEC_unordered_remove (graphite_bb_p, SCOP_BBS (scop), i); - free_graphite_bb (gb); - /* XXX: Hackish? But working. */ - i--; - } - - graphite_sort_gbbs (scop); -} - /* Move the loop at index LOOP and insert it before index NEW_LOOP_POS. This transformartion is only valid, if the loop nest between i and k is perfectly nested. Therefore we do not need to change the static schedule. @@ -4963,11 +5478,6 @@ graphite_trans_loop_block (VEC (graphite_bb_p, heap) *bbs, int loops) /* TODO: - Calculate the stride size automatically. */ int stride_size = 64; - /* It makes no sense to block a single loop. */ - for (i = 0; VEC_iterate (graphite_bb_p, bbs, i, gb); i++) - if (gbb_nb_loops (gb) < 2) - return false; - for (i = 0; VEC_iterate (graphite_bb_p, bbs, i, gb); i++) transform_done |= graphite_trans_bb_block (gb, stride_size, loops); @@ -5050,7 +5560,7 @@ graphite_trans_scop_block (scop_p scop) j++; /* Found perfect loop nest. */ - if (perfect && last_nb_loops - j > 0) + if (perfect && last_nb_loops - j >= 2) transform_done |= graphite_trans_loop_block (bbs, last_nb_loops - j); /* Check if we start with a new loop. @@ -5109,7 +5619,6 @@ graphite_apply_transformations (scop_p scop) /* Sort the list of bbs. Keep them always sorted. */ graphite_sort_gbbs (scop); - scop_remove_ignoreable_gbbs (scop); if (flag_loop_block) transform_done = graphite_trans_scop_block (scop); @@ -5158,13 +5667,15 @@ limit_scops (void) int j; loop_p loop; build_scop_bbs (scop); - build_scop_loop_nests (scop); + + if (!build_scop_loop_nests (scop)) + continue; for (j = 0; VEC_iterate (loop_p, SCOP_LOOP_NEST (scop), j, loop); j++) if (!loop_in_scop_p (loop_outer (loop), scop)) { sd_region open_scop; - open_scop.entry = loop_preheader_edge (loop)->dest; + open_scop.entry = loop->header; open_scop.exit = single_exit (loop)->dest; VEC_safe_push (sd_region, heap, tmp_scops, &open_scop); } @@ -5191,13 +5702,12 @@ graphite_transform_loops (void) return; current_scops = VEC_alloc (scop_p, heap, 3); - - calculate_dominance_info (CDI_DOMINATORS); - calculate_dominance_info (CDI_POST_DOMINATORS); + recompute_all_dominators (); if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, "Graphite loop transformations \n"); + initialize_original_copy_tables (); cloog_initialize (); build_scops (); limit_scops (); @@ -5209,9 +5719,12 @@ graphite_transform_loops (void) for (i = 0; VEC_iterate (scop_p, current_scops, i, scop); i++) { build_scop_bbs (scop); - build_scop_loop_nests (scop); + if (!build_scop_loop_nests (scop)) + continue; + build_scop_canonical_schedules (scop); build_bb_loops (scop); + build_scop_conditions (scop); find_scop_parameters (scop); build_scop_context (scop); @@ -5227,8 +5740,8 @@ graphite_transform_loops (void) if (!build_scop_iteration_domain (scop)) continue; - build_scop_conditions (scop); build_scop_data_accesses (scop); + build_scop_dynamic_schedules (scop); if (dump_file && (dump_flags & TDF_DETAILS)) { @@ -5238,11 +5751,19 @@ graphite_transform_loops (void) if (graphite_apply_transformations (scop)) gloog (scop, find_transform (scop)); +#ifdef ENABLE_CHECKING + else + { + struct clast_stmt *stmt = find_transform (scop); + cloog_clast_free (stmt); + } +#endif } /* Cleanup. */ free_scops (current_scops); cloog_finalize (); + free_original_copy_tables (); } #else /* If Cloog is not available: #ifndef HAVE_cloog. */ diff --git a/gcc/graphite.h b/gcc/graphite.h index 2e2904a6ab..92a68167f2 100644 --- a/gcc/graphite.h +++ b/gcc/graphite.h @@ -18,6 +18,9 @@ You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see . */ +#ifndef GCC_GRAPHITE_H +#define GCC_GRAPHITE_H + #include "tree-data-ref.h" typedef struct graphite_bb *graphite_bb_p; @@ -31,7 +34,7 @@ static inline int scop_nb_loops (scop_p scop); static inline unsigned scop_nb_params (scop_p scop); static inline bool scop_contains_loop (scop_p scop, struct loop *loop); -struct graphite_bb +typedef struct graphite_bb { basic_block bb; scop_p scop; @@ -116,7 +119,7 @@ struct graphite_bb CloogMatrix *domain; /* Lists containing the restrictions of the conditional statements - dominating this bb. This bb can only be executed, if all conditions + dominating this bb. This bb can only be executed, if all conditions are true. Example: @@ -129,13 +132,13 @@ struct graphite_bb B } - So for B there is a additional condition (2i <= 8). + So for B there is an additional condition (2i <= 8). - TODO: Add this restrictions to the domain matrix. + TODO: Add these restrictions to the domain matrix. - List of COND_EXPR and SWITCH_EXPR. A COND_EXPR is true only if the - corresponding element in CONDITION_CASES is not NULL_TREE. For a - SWITCH_EXPR the corresponding element in CONDITION_CASES is a + List of COND_EXPR and SWITCH_EXPR. A COND_EXPR is true only if the + corresponding element in CONDITION_CASES is not NULL_TREE. For a + SWITCH_EXPR the corresponding element in CONDITION_CASES is a CASE_LABEL_EXPR. */ VEC (gimple, heap) *conditions; VEC (gimple, heap) *condition_cases; @@ -190,7 +193,8 @@ struct graphite_bb lambda_vector compressed_alpha_matrix; CloogMatrix *dynamic_schedule; VEC (data_reference_p, heap) *data_refs; -}; + htab_t cloog_iv_types; +} *gbb_p; #define GBB_BB(GBB) GBB->bb #define GBB_SCOP(GBB) GBB->scop @@ -202,6 +206,7 @@ struct graphite_bb #define GBB_CONDITIONS(GBB) GBB->conditions #define GBB_CONDITION_CASES(GBB) GBB->condition_cases #define GBB_LOOPS(GBB) GBB->loops +#define GBB_CLOOG_IV_TYPES(GBB) GBB->cloog_iv_types /* Return the loop that contains the basic block GBB. */ @@ -234,7 +239,7 @@ gbb_loop_at_index (graphite_bb_p gb, int index) return VEC_index (loop_p, GBB_LOOPS (gb), index); } -/* Returns the corresponding loop iterator index for a gimple loop. */ +/* Returns the index of LOOP in the loop nest around GB. */ static inline int gbb_loop_index (graphite_bb_p gb, loop_p loop) @@ -271,10 +276,12 @@ DEF_VEC_ALLOC_P (name_tree, heap); typedef struct sese { edge entry, exit; + struct pointer_set_t *region_basic_blocks; } *sese; #define SESE_ENTRY(S) (S->entry) #define SESE_EXIT(S) (S->exit) +#define SESE_REGION_BBS(S) (S->region_basic_blocks) /* A SCOP is a Static Control Part of the program, simple enough to be represented in polyhedral form. */ @@ -305,8 +312,13 @@ struct scop /* ??? It looks like a global mapping loop_id -> cloog_loop would work. */ htab_t loop2cloog_loop; - /* CLooG representation of this SCOP. */ + /* Cloog representation of this scop. */ CloogProgram *program; + + /* Are we allowed to add more params? This is for debugging purpose. We + can only add new params before generating the bb domains, otherwise they + become invalid. */ + bool add_params; }; #define SCOP_BBS(S) S->bbs @@ -319,9 +331,11 @@ struct scop but just a boundary. SCOP_ENTRY is considered part of the scop. */ #define SCOP_ENTRY(S) (SESE_ENTRY (SCOP_REGION (S))->dest) #define SCOP_EXIT(S) (SESE_EXIT (SCOP_REGION (S))->dest) +#define SCOP_REGION_BBS(S) (SESE_REGION_BBS (SCOP_REGION (S))) #define SCOP_STATIC_SCHEDULE(S) S->static_schedule #define SCOP_LOOPS(S) S->loops #define SCOP_LOOP_NEST(S) S->loop_nest +#define SCOP_ADD_PARAMS(S) S->add_params #define SCOP_PARAMS(S) S->params #define SCOP_OLDIVS(S) S->old_ivs #define SCOP_PROG(S) S->program @@ -335,9 +349,9 @@ extern void debug_gbb (graphite_bb_p, int); extern void dot_scop (scop_p); extern void dot_all_scops (void); extern void debug_clast_stmt (struct clast_stmt *); - - -extern void debug_loop_vec (graphite_bb_p gb); +extern void debug_rename_map (htab_t); +extern void debug_ivtype_map (htab_t); +extern void debug_loop_vec (graphite_bb_p); extern void debug_oldivs (scop_p); /* Describes the type of an iv stack entry. */ @@ -369,6 +383,24 @@ DEF_VEC_ALLOC_P(iv_stack_entry_p,heap); typedef VEC(iv_stack_entry_p, heap) **loop_iv_stack; extern void debug_loop_iv_stack (loop_iv_stack); +/* Return the old induction variable of the LOOP that is in normal + form in SCOP. */ + +static inline tree +oldiv_for_loop (scop_p scop, loop_p loop) +{ + int i; + name_tree iv; + + if (!loop) + return NULL_TREE; + + for (i = 0; VEC_iterate (name_tree, SCOP_OLDIVS (scop), i, iv); i++) + if (iv->loop == loop) + return iv->t; + + return NULL_TREE; +} /* Return the number of gimple loops contained in SCOP. */ @@ -422,15 +454,6 @@ loop_domain_dim (unsigned int loop_num, scop_p scop) return cloog_domain_dim (cloog_loop_domain (slot->cloog_loop)) + 2; } -/* Returns the dimensionality of an enclosing loop iteration domain - with respect to enclosing SCoP for a given data reference REF. */ - -static inline int -ref_nb_loops (data_reference_p ref) -{ - return loop_domain_dim (loop_containing_stmt (DR_STMT (ref))->num, DR_SCOP (ref)); -} - /* Returns the dimensionality of a loop iteration vector in a loop iteration domain for a given loop (identified by LOOP_NUM) with respect to SCOP. */ @@ -521,22 +544,59 @@ scop_gimple_loop_depth (scop_p scop, loop_p loop) return depth; } -/* Associate a POLYHEDRON dependence description to two data - references A and B. */ -struct data_dependence_polyhedron +/* Static inline function prototypes. */ + +static inline unsigned scop_nb_params (scop_p scop); + +/* Returns true when BB is in SCOP. */ + +static inline bool +bb_in_scop_p (basic_block bb, scop_p scop) +{ + return bitmap_bit_p (SCOP_BBS_B (scop), bb->index); +} + +/* Returns true when LOOP is in SCOP. */ + +static inline bool +loop_in_scop_p (struct loop *loop, scop_p scop) { - struct data_reference *a; - struct data_reference *b; - bool reversed_p; - bool loop_carried; /*TODO:konrad get rid of this, make level signed */ - signed level; - CloogDomain *polyhedron; -}; + return (bb_in_scop_p (loop->header, scop) + && bb_in_scop_p (loop->latch, scop)); +} + +/* Calculate the number of loops around LOOP in the SCOP. */ + +static inline int +nb_loops_around_loop_in_scop (struct loop *l, scop_p scop) +{ + int d = 0; + + for (; loop_in_scop_p (l, scop); d++, l = loop_outer (l)); -#define RDGE_DDP(E) ((struct data_dependence_polyhedron*) ((E)->data)) + return d; +} + +/* Calculate the number of loops around GB in the current SCOP. */ + +static inline int +nb_loops_around_gb (graphite_bb_p gb) +{ + return nb_loops_around_loop_in_scop (gbb_loop (gb), GBB_SCOP (gb)); +} -typedef struct data_dependence_polyhedron *ddp_p; +/* Returns the dimensionality of an enclosing loop iteration domain + with respect to enclosing SCoP for a given data reference REF. The + returned dimensionality is homogeneous (depth of loop nest + number + of SCoP parameters + const). */ + +static inline int +ref_nb_loops (data_reference_p ref) +{ + loop_p loop = loop_containing_stmt (DR_STMT (ref)); + scop_p scop = DR_SCOP (ref); -DEF_VEC_P(ddp_p); -DEF_VEC_ALLOC_P(ddp_p,heap); + return nb_loops_around_loop_in_scop (loop, scop) + scop_nb_params (scop) + 2; +} +#endif /* GCC_GRAPHITE_H */ diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c index 662cff60b5..35ec9a60f8 100644 --- a/gcc/ipa-inline.c +++ b/gcc/ipa-inline.c @@ -1528,6 +1528,7 @@ cgraph_early_inlining (void) todo = optimize_inline_calls (current_function_decl); timevar_pop (TV_INTEGRATION); } + cfun->always_inline_functions_inlined = true; return todo; } diff --git a/gcc/ira-build.c b/gcc/ira-build.c index b10aa460ce..9e47333d46 100644 --- a/gcc/ira-build.c +++ b/gcc/ira-build.c @@ -1583,8 +1583,8 @@ propagate_allocno_info (void) ira_loop_tree_node_t parent; enum reg_class cover_class; - if (flag_ira_algorithm != IRA_ALGORITHM_REGIONAL - && flag_ira_algorithm != IRA_ALGORITHM_MIXED) + if (flag_ira_region != IRA_REGION_ALL + && flag_ira_region != IRA_REGION_MIXED) return; for (i = max_reg_num () - 1; i >= FIRST_PSEUDO_REGISTER; i--) for (a = ira_regno_allocno_map[i]; @@ -2116,9 +2116,10 @@ setup_min_max_allocno_live_range_point (void) } /* Sort allocnos according to their live ranges. Allocnos with - smaller cover class are put first. Allocnos with the same cove - class are ordered according their start (min). Allocnos with the - same start are ordered according their finish (max). */ + smaller cover class are put first unless we use priority coloring. + Allocnos with the same cove class are ordered according their start + (min). Allocnos with the same start are ordered according their + finish (max). */ static int allocno_range_compare_func (const void *v1p, const void *v2p) { @@ -2126,7 +2127,8 @@ allocno_range_compare_func (const void *v1p, const void *v2p) ira_allocno_t a1 = *(const ira_allocno_t *) v1p; ira_allocno_t a2 = *(const ira_allocno_t *) v2p; - if ((diff = ALLOCNO_COVER_CLASS (a1) - ALLOCNO_COVER_CLASS (a2)) != 0) + if (flag_ira_algorithm != IRA_ALGORITHM_PRIORITY + && (diff = ALLOCNO_COVER_CLASS (a1) - ALLOCNO_COVER_CLASS (a2)) != 0) return diff; if ((diff = ALLOCNO_MIN (a1) - ALLOCNO_MIN (a2)) != 0) return diff; @@ -2161,7 +2163,7 @@ sort_conflict_id_allocno_map (void) static void setup_min_max_conflict_allocno_ids (void) { - enum reg_class cover_class; + int cover_class; int i, j, min, max, start, finish, first_not_finished, filled_area_start; int *live_range_min, *last_lived; ira_allocno_t a; @@ -2174,7 +2176,9 @@ setup_min_max_conflict_allocno_ids (void) a = ira_conflict_id_allocno_map[i]; if (a == NULL) continue; - if (cover_class != ALLOCNO_COVER_CLASS (a)) + if (cover_class < 0 + || (flag_ira_algorithm != IRA_ALGORITHM_PRIORITY + && cover_class != (int) ALLOCNO_COVER_CLASS (a))) { cover_class = ALLOCNO_COVER_CLASS (a); min = i; @@ -2208,7 +2212,9 @@ setup_min_max_conflict_allocno_ids (void) a = ira_conflict_id_allocno_map[i]; if (a == NULL) continue; - if (cover_class != ALLOCNO_COVER_CLASS (a)) + if (cover_class < 0 + || (flag_ira_algorithm != IRA_ALGORITHM_PRIORITY + && cover_class != (int) ALLOCNO_COVER_CLASS (a))) { cover_class = ALLOCNO_COVER_CLASS (a); for (j = 0; j < ira_max_point; j++) @@ -2503,7 +2509,8 @@ ira_flattening (int max_regno_before_emit, int ira_max_point_before_emit) { ira_allocno_t live_a = ira_allocnos[n]; - if (cover_class == ALLOCNO_COVER_CLASS (live_a) + if (ira_reg_classes_intersect_p + [cover_class][ALLOCNO_COVER_CLASS (live_a)] /* Don't set up conflict for the allocno with itself. */ && num != (int) n) ira_add_allocno_conflict (a, live_a); diff --git a/gcc/ira-color.c b/gcc/ira-color.c index 4b9909194d..c9cb1845fe 100644 --- a/gcc/ira-color.c +++ b/gcc/ira-color.c @@ -279,7 +279,8 @@ update_copy_costs (ira_allocno_t allocno, bool decr_p) else gcc_unreachable (); - if (cover_class != ALLOCNO_COVER_CLASS (another_allocno) + cover_class = ALLOCNO_COVER_CLASS (another_allocno); + if (! ira_reg_classes_intersect_p[rclass][cover_class] || ALLOCNO_ASSIGNED_P (another_allocno)) continue; @@ -301,6 +302,8 @@ update_copy_costs (ira_allocno_t allocno, bool decr_p) (&ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (another_allocno), cover_class, 0, ALLOCNO_CONFLICT_HARD_REG_COSTS (another_allocno)); + i = ira_class_hard_reg_index[cover_class][hard_regno]; + ira_assert (i >= 0); ALLOCNO_UPDATED_HARD_REG_COSTS (another_allocno)[i] += update_cost; ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (another_allocno)[i] += update_cost; @@ -311,17 +314,19 @@ update_copy_costs (ira_allocno_t allocno, bool decr_p) while (get_next_update_cost (&allocno, &divisor)); } -/* This function updates COSTS (decrease if DECR_P) by conflict costs - of the unassigned allocnos connected by copies with allocnos in - update_cost_queue. This update increases chances to remove some - copies. */ +/* This function updates COSTS (decrease if DECR_P) for hard_registers + of COVER_CLASS by conflict costs of the unassigned allocnos + connected by copies with allocnos in update_cost_queue. This + update increases chances to remove some copies. */ static void -update_conflict_hard_regno_costs (int *costs, bool decr_p) +update_conflict_hard_regno_costs (int *costs, enum reg_class cover_class, + bool decr_p) { int i, cost, class_size, freq, mult, div, divisor; + int index, hard_regno; int *conflict_costs; bool cont_p; - enum reg_class cover_class; + enum reg_class another_cover_class; ira_allocno_t allocno, another_allocno; ira_copy_t cp, next_cp; @@ -340,16 +345,17 @@ update_conflict_hard_regno_costs (int *costs, bool decr_p) } else gcc_unreachable (); - cover_class = ALLOCNO_COVER_CLASS (allocno); - if (cover_class != ALLOCNO_COVER_CLASS (another_allocno) + another_cover_class = ALLOCNO_COVER_CLASS (another_allocno); + if (! ira_reg_classes_intersect_p[cover_class][another_cover_class] || ALLOCNO_ASSIGNED_P (another_allocno) || ALLOCNO_MAY_BE_SPILLED_P (ALLOCNO_FIRST_COALESCED_ALLOCNO (another_allocno))) continue; - class_size = ira_class_hard_regs_num[cover_class]; + class_size = ira_class_hard_regs_num[another_cover_class]; ira_allocate_and_copy_costs (&ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (another_allocno), - cover_class, ALLOCNO_CONFLICT_HARD_REG_COSTS (another_allocno)); + another_cover_class, + ALLOCNO_CONFLICT_HARD_REG_COSTS (another_allocno)); conflict_costs = ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (another_allocno); if (conflict_costs == NULL) @@ -364,13 +370,18 @@ update_conflict_hard_regno_costs (int *costs, bool decr_p) cont_p = false; for (i = class_size - 1; i >= 0; i--) { + hard_regno = ira_class_hard_regs[another_cover_class][i]; + ira_assert (hard_regno >= 0); + index = ira_class_hard_reg_index[cover_class][hard_regno]; + if (index < 0) + continue; cost = conflict_costs [i] * mult / div; if (cost == 0) continue; cont_p = true; if (decr_p) cost = -cost; - costs[i] += cost; + costs[index] += cost; } } /* Probably 5 hops will be enough. */ @@ -429,11 +440,11 @@ static bool assign_hard_reg (ira_allocno_t allocno, bool retry_p) { HARD_REG_SET conflicting_regs; - int i, j, hard_regno, best_hard_regno, class_size; + int i, j, k, hard_regno, best_hard_regno, class_size; int cost, mem_cost, min_cost, full_cost, min_full_cost, add_cost; int *a_costs; int *conflict_costs; - enum reg_class cover_class, rclass; + enum reg_class cover_class, rclass, conflict_cover_class; enum machine_mode mode; ira_allocno_t a, conflict_allocno; ira_allocno_conflict_iterator aci; @@ -490,7 +501,9 @@ assign_hard_reg (ira_allocno_t allocno, bool retry_p) if (retry_p || bitmap_bit_p (consideration_allocno_bitmap, ALLOCNO_NUM (conflict_allocno))) { - ira_assert (cover_class == ALLOCNO_COVER_CLASS (conflict_allocno)); + conflict_cover_class = ALLOCNO_COVER_CLASS (conflict_allocno); + ira_assert (ira_reg_classes_intersect_p + [cover_class][conflict_cover_class]); if (allocno_coalesced_p) { if (bitmap_bit_p (processed_coalesced_allocno_bitmap, @@ -501,7 +514,8 @@ assign_hard_reg (ira_allocno_t allocno, bool retry_p) } if (ALLOCNO_ASSIGNED_P (conflict_allocno)) { - if ((hard_regno = ALLOCNO_HARD_REGNO (conflict_allocno)) >= 0) + if ((hard_regno = ALLOCNO_HARD_REGNO (conflict_allocno)) >= 0 + && ira_class_hard_reg_index[cover_class][hard_regno] >= 0) { IOR_HARD_REG_SET (conflicting_regs, @@ -511,20 +525,27 @@ assign_hard_reg (ira_allocno_t allocno, bool retry_p) conflicting_regs)) goto fail; } - continue; } else if (! ALLOCNO_MAY_BE_SPILLED_P (ALLOCNO_FIRST_COALESCED_ALLOCNO (conflict_allocno))) { ira_allocate_and_copy_costs (&ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (conflict_allocno), - cover_class, + conflict_cover_class, ALLOCNO_CONFLICT_HARD_REG_COSTS (conflict_allocno)); conflict_costs = ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (conflict_allocno); if (conflict_costs != NULL) for (j = class_size - 1; j >= 0; j--) - full_costs[j] -= conflict_costs[j]; + { + hard_regno = ira_class_hard_regs[cover_class][j]; + ira_assert (hard_regno >= 0); + k = (ira_class_hard_reg_index + [conflict_cover_class][hard_regno]); + if (k < 0) + continue; + full_costs[j] -= conflict_costs[k]; + } queue_update_cost (conflict_allocno, COST_HOP_DIVISOR); } } @@ -533,7 +554,7 @@ assign_hard_reg (ira_allocno_t allocno, bool retry_p) } /* Take into account preferences of allocnos connected by copies to the conflict allocnos. */ - update_conflict_hard_regno_costs (full_costs, true); + update_conflict_hard_regno_costs (full_costs, cover_class, true); /* Take preferences of allocnos connected by copies into account. */ @@ -545,7 +566,7 @@ assign_hard_reg (ira_allocno_t allocno, bool retry_p) if (a == allocno) break; } - update_conflict_hard_regno_costs (full_costs, false); + update_conflict_hard_regno_costs (full_costs, cover_class, false); min_cost = min_full_cost = INT_MAX; /* We don't care about giving callee saved registers to allocnos no living through calls because call clobbered registers are @@ -594,7 +615,8 @@ assign_hard_reg (ira_allocno_t allocno, bool retry_p) best_hard_regno = -1; } fail: - if (best_hard_regno < 0 + if (flag_ira_algorithm != IRA_ALGORITHM_PRIORITY + && best_hard_regno < 0 && ALLOCNO_NEXT_COALESCED_ALLOCNO (allocno) != allocno) { for (j = 0, a = ALLOCNO_NEXT_COALESCED_ALLOCNO (allocno);; @@ -1605,6 +1627,10 @@ coalesce_allocnos (bool reload_p) { next_cp = cp->next_first_allocno_copy; regno = ALLOCNO_REGNO (cp->second); + /* For priority coloring we coalesce allocnos only with + the same cover class not with intersected cover + classes as it were possible. It is done for + simplicity. */ if ((reload_p || (ALLOCNO_COVER_CLASS (cp->second) == cover_class && ALLOCNO_MODE (cp->second) == mode)) @@ -1659,12 +1685,72 @@ coalesce_allocnos (bool reload_p) ira_free (sorted_copies); } +/* Map: allocno number -> allocno priority. */ +static int *allocno_priorities; + +/* Set up priorities for N allocnos in array + CONSIDERATION_ALLOCNOS. */ +static void +setup_allocno_priorities (ira_allocno_t *consideration_allocnos, int n) +{ + int i, length, nrefs, priority, max_priority, mult; + ira_allocno_t a; + + max_priority = 0; + for (i = 0; i < n; i++) + { + a = consideration_allocnos[i]; + nrefs = ALLOCNO_NREFS (a); + ira_assert (nrefs >= 0); + mult = floor_log2 (ALLOCNO_NREFS (a)) + 1; + ira_assert (mult >= 0); + allocno_priorities[ALLOCNO_NUM (a)] + = priority + = (mult + * (ALLOCNO_MEMORY_COST (a) - ALLOCNO_COVER_CLASS_COST (a)) + * ira_reg_class_nregs[ALLOCNO_COVER_CLASS (a)][ALLOCNO_MODE (a)]); + if (priority < 0) + priority = -priority; + if (max_priority < priority) + max_priority = priority; + } + mult = max_priority == 0 ? 1 : INT_MAX / max_priority; + for (i = 0; i < n; i++) + { + a = consideration_allocnos[i]; + length = ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a); + if (length <= 0) + length = 1; + allocno_priorities[ALLOCNO_NUM (a)] + = allocno_priorities[ALLOCNO_NUM (a)] * mult / length; + } +} + +/* Sort allocnos according to their priorities which are calculated + analogous to ones in file `global.c'. */ +static int +allocno_priority_compare_func (const void *v1p, const void *v2p) +{ + ira_allocno_t a1 = *(const ira_allocno_t *) v1p; + ira_allocno_t a2 = *(const ira_allocno_t *) v2p; + int pri1, pri2; + + pri1 = allocno_priorities[ALLOCNO_NUM (a1)]; + pri2 = allocno_priorities[ALLOCNO_NUM (a2)]; + if (pri2 - pri1) + return pri2 - pri1; + + /* If regs are equally good, sort by allocnos, so that the results of + qsort leave nothing to chance. */ + return ALLOCNO_NUM (a1) - ALLOCNO_NUM (a2); +} + /* Chaitin-Briggs coloring for allocnos in COLORING_ALLOCNO_BITMAP taking into account allocnos in CONSIDERATION_ALLOCNO_BITMAP. */ static void color_allocnos (void) { - unsigned int i; + unsigned int i, n; bitmap_iterator bi; ira_allocno_t a; @@ -1672,30 +1758,83 @@ color_allocnos (void) processed_coalesced_allocno_bitmap = ira_allocate_bitmap (); if (flag_ira_coalesce) coalesce_allocnos (false); - /* Put the allocnos into the corresponding buckets. */ - colorable_allocno_bucket = NULL; - uncolorable_allocno_bucket = NULL; - EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi) + if (flag_ira_algorithm == IRA_ALGORITHM_PRIORITY) { - a = ira_allocnos[i]; - if (ALLOCNO_COVER_CLASS (a) == NO_REGS) + n = 0; + EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi) { - ALLOCNO_HARD_REGNO (a) = -1; - ALLOCNO_ASSIGNED_P (a) = true; - ira_assert (ALLOCNO_UPDATED_HARD_REG_COSTS (a) == NULL); - ira_assert (ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a) == NULL); - if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL) + a = ira_allocnos[i]; + if (ALLOCNO_COVER_CLASS (a) == NO_REGS) { - fprintf (ira_dump_file, " Spill"); - print_coalesced_allocno (a); - fprintf (ira_dump_file, "\n"); + ALLOCNO_HARD_REGNO (a) = -1; + ALLOCNO_ASSIGNED_P (a) = true; + ira_assert (ALLOCNO_UPDATED_HARD_REG_COSTS (a) == NULL); + ira_assert (ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a) == NULL); + if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL) + { + fprintf (ira_dump_file, " Spill"); + print_coalesced_allocno (a); + fprintf (ira_dump_file, "\n"); + } + continue; } - continue; + sorted_allocnos[n++] = a; } - put_allocno_into_bucket (a); + if (n != 0) + { + setup_allocno_priorities (sorted_allocnos, n); + qsort (sorted_allocnos, n, sizeof (ira_allocno_t), + allocno_priority_compare_func); + for (i = 0; i < n; i++) + { + a = sorted_allocnos[i]; + if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL) + { + fprintf (ira_dump_file, " "); + print_coalesced_allocno (a); + fprintf (ira_dump_file, " -- "); + } + if (assign_hard_reg (a, false)) + { + if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL) + fprintf (ira_dump_file, "assign hard reg %d\n", + ALLOCNO_HARD_REGNO (a)); + } + else + { + if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL) + fprintf (ira_dump_file, "assign memory\n"); + } + } + } + } + else + { + /* Put the allocnos into the corresponding buckets. */ + colorable_allocno_bucket = NULL; + uncolorable_allocno_bucket = NULL; + EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi) + { + a = ira_allocnos[i]; + if (ALLOCNO_COVER_CLASS (a) == NO_REGS) + { + ALLOCNO_HARD_REGNO (a) = -1; + ALLOCNO_ASSIGNED_P (a) = true; + ira_assert (ALLOCNO_UPDATED_HARD_REG_COSTS (a) == NULL); + ira_assert (ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a) == NULL); + if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL) + { + fprintf (ira_dump_file, " Spill"); + print_coalesced_allocno (a); + fprintf (ira_dump_file, "\n"); + } + continue; + } + put_allocno_into_bucket (a); + } + push_allocnos_to_stack (); + pop_allocnos_from_stack (); } - push_allocnos_to_stack (); - pop_allocnos_from_stack (); if (flag_ira_coalesce) /* We don't need coalesced allocnos for ira_reassign_pseudos. */ EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi) @@ -1796,8 +1935,8 @@ color_pass (ira_loop_tree_node_t loop_tree_node) /* Color all mentioned allocnos including transparent ones. */ color_allocnos (); /* Process caps. They are processed just once. */ - if (flag_ira_algorithm == IRA_ALGORITHM_MIXED - || flag_ira_algorithm == IRA_ALGORITHM_REGIONAL) + if (flag_ira_region == IRA_REGION_MIXED + || flag_ira_region == IRA_REGION_ALL) EXECUTE_IF_SET_IN_BITMAP (loop_tree_node->all_allocnos, 0, j, bi) { a = ira_allocnos[j]; @@ -1806,9 +1945,9 @@ color_pass (ira_loop_tree_node_t loop_tree_node) /* Remove from processing in the next loop. */ bitmap_clear_bit (consideration_allocno_bitmap, j); rclass = ALLOCNO_COVER_CLASS (a); - if ((flag_ira_algorithm == IRA_ALGORITHM_MIXED - && loop_tree_node->reg_pressure[rclass] - <= ira_available_class_regs[rclass])) + if (flag_ira_region == IRA_REGION_MIXED + && (loop_tree_node->reg_pressure[rclass] + <= ira_available_class_regs[rclass])) { mode = ALLOCNO_MODE (a); hard_regno = ALLOCNO_HARD_REGNO (a); @@ -1843,6 +1982,7 @@ color_pass (ira_loop_tree_node_t loop_tree_node) mode = ALLOCNO_MODE (a); rclass = ALLOCNO_COVER_CLASS (a); hard_regno = ALLOCNO_HARD_REGNO (a); + /* Use hard register class here. ??? */ if (hard_regno >= 0) { index = ira_class_hard_reg_index[rclass][hard_regno]; @@ -1854,9 +1994,10 @@ color_pass (ira_loop_tree_node_t loop_tree_node) if (subloop_allocno == NULL || ALLOCNO_CAP (subloop_allocno) != NULL) continue; + ira_assert (ALLOCNO_COVER_CLASS (subloop_allocno) == rclass); ira_assert (bitmap_bit_p (subloop_node->all_allocnos, ALLOCNO_NUM (subloop_allocno))); - if (flag_ira_algorithm == IRA_ALGORITHM_MIXED + if ((flag_ira_region == IRA_REGION_MIXED) && (loop_tree_node->reg_pressure[rclass] <= ira_available_class_regs[rclass])) { @@ -2002,6 +2143,7 @@ move_spill_restore (void) subloop_allocno = subloop_node->regno_allocno_map[regno]; if (subloop_allocno == NULL) continue; + ira_assert (rclass == ALLOCNO_COVER_CLASS (subloop_allocno)); /* We have accumulated cost. To get the real cost of allocno usage in the loop we should subtract costs of the subloop allocnos. */ @@ -2027,6 +2169,7 @@ move_spill_restore (void) if ((parent = loop_node->parent) != NULL && (parent_allocno = parent->regno_allocno_map[regno]) != NULL) { + ira_assert (rclass == ALLOCNO_COVER_CLASS (parent_allocno)); exit_freq = ira_loop_edge_freq (loop_node, regno, true); enter_freq = ira_loop_edge_freq (loop_node, regno, false); if ((hard_regno2 = ALLOCNO_HARD_REGNO (parent_allocno)) < 0) @@ -2094,13 +2237,15 @@ update_curr_costs (ira_allocno_t a) } else gcc_unreachable (); - if (cover_class != ALLOCNO_COVER_CLASS (another_a) + if (! ira_reg_classes_intersect_p[cover_class][ALLOCNO_COVER_CLASS + (another_a)] || ! ALLOCNO_ASSIGNED_P (another_a) || (hard_regno = ALLOCNO_HARD_REGNO (another_a)) < 0) continue; rclass = REGNO_REG_CLASS (hard_regno); i = ira_class_hard_reg_index[cover_class][hard_regno]; - ira_assert (i >= 0); + if (i < 0) + continue; cost = (cp->first == a ? ira_register_move_cost[mode][rclass][cover_class] : ira_register_move_cost[mode][cover_class][rclass]); @@ -2116,66 +2261,6 @@ update_curr_costs (ira_allocno_t a) } } -/* Map: allocno number -> allocno priority. */ -static int *allocno_priorities; - -/* Set up priorities for N allocnos in array - CONSIDERATION_ALLOCNOS. */ -static void -setup_allocno_priorities (ira_allocno_t *consideration_allocnos, int n) -{ - int i, length, nrefs, priority, max_priority, mult; - ira_allocno_t a; - - max_priority = 0; - for (i = 0; i < n; i++) - { - a = consideration_allocnos[i]; - nrefs = ALLOCNO_NREFS (a); - ira_assert (nrefs >= 0); - mult = floor_log2 (ALLOCNO_NREFS (a)) + 1; - ira_assert (mult >= 0); - allocno_priorities[ALLOCNO_NUM (a)] - = priority - = (mult - * (ALLOCNO_MEMORY_COST (a) - ALLOCNO_COVER_CLASS_COST (a)) - * ira_reg_class_nregs[ALLOCNO_COVER_CLASS (a)][ALLOCNO_MODE (a)]); - if (priority < 0) - priority = -priority; - if (max_priority < priority) - max_priority = priority; - } - mult = max_priority == 0 ? 1 : INT_MAX / max_priority; - for (i = 0; i < n; i++) - { - a = consideration_allocnos[i]; - length = ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a); - if (length <= 0) - length = 1; - allocno_priorities[ALLOCNO_NUM (a)] - = allocno_priorities[ALLOCNO_NUM (a)] * mult / length; - } -} - -/* Sort allocnos according to their priorities which are calculated - analogous to ones in file `global.c'. */ -static int -allocno_priority_compare_func (const void *v1p, const void *v2p) -{ - ira_allocno_t a1 = *(const ira_allocno_t *) v1p; - ira_allocno_t a2 = *(const ira_allocno_t *) v2p; - int pri1, pri2; - - pri1 = allocno_priorities[ALLOCNO_NUM (a1)]; - pri2 = allocno_priorities[ALLOCNO_NUM (a2)]; - if (pri2 - pri1) - return pri2 - pri1; - - /* If regs are equally good, sort by allocnos, so that the results of - qsort leave nothing to chance. */ - return ALLOCNO_NUM (a1) - ALLOCNO_NUM (a2); -} - /* Try to assign hard registers to the unassigned allocnos and allocnos conflicting with them or conflicting with allocnos whose regno >= START_REGNO. The function is called after ira_flattening, @@ -2215,7 +2300,8 @@ ira_reassign_conflict_allocnos (int start_regno) continue; FOR_EACH_ALLOCNO_CONFLICT (a, conflict_a, aci) { - ira_assert (cover_class == ALLOCNO_COVER_CLASS (conflict_a)); + ira_assert (ira_reg_classes_intersect_p + [cover_class][ALLOCNO_COVER_CLASS (conflict_a)]); if (bitmap_bit_p (allocnos_to_color, ALLOCNO_NUM (conflict_a))) continue; bitmap_set_bit (allocnos_to_color, ALLOCNO_NUM (conflict_a)); diff --git a/gcc/ira-conflicts.c b/gcc/ira-conflicts.c index 6e7d7692b6..ff116b5da8 100644 --- a/gcc/ira-conflicts.c +++ b/gcc/ira-conflicts.c @@ -114,7 +114,8 @@ build_conflict_bit_table (void) EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, j) { live_a = ira_allocnos[j]; - if (cover_class == ALLOCNO_COVER_CLASS (live_a) + if (ira_reg_classes_intersect_p + [cover_class][ALLOCNO_COVER_CLASS (live_a)] /* Don't set up conflict for the allocno with itself. */ && num != (int) j) { @@ -555,8 +556,8 @@ build_allocno_conflicts (ira_allocno_t a) ALLOCNO_MIN (a), ALLOCNO_MAX (a), i, asi) { another_a = ira_conflict_id_allocno_map[i]; - ira_assert (ALLOCNO_COVER_CLASS (a) - == ALLOCNO_COVER_CLASS (another_a)); + ira_assert (ira_reg_classes_intersect_p + [ALLOCNO_COVER_CLASS (a)][ALLOCNO_COVER_CLASS (another_a)]); collected_conflict_allocnos[px++] = another_a; } if (ira_conflict_vector_profitable_p (a, px)) @@ -592,8 +593,8 @@ build_allocno_conflicts (ira_allocno_t a) ALLOCNO_MIN (a), ALLOCNO_MAX (a), i, asi) { another_a = ira_conflict_id_allocno_map[i]; - ira_assert (ALLOCNO_COVER_CLASS (a) - == ALLOCNO_COVER_CLASS (another_a)); + ira_assert (ira_reg_classes_intersect_p + [ALLOCNO_COVER_CLASS (a)][ALLOCNO_COVER_CLASS (another_a)]); if ((another_parent_a = ALLOCNO_CAP (another_a)) == NULL && (another_parent_a = (parent->regno_allocno_map [ALLOCNO_REGNO (another_a)])) == NULL) @@ -740,6 +741,7 @@ ira_build_conflicts (void) { ira_allocno_t a; ira_allocno_iterator ai; + HARD_REG_SET temp_hard_reg_set; if (optimize) { @@ -747,8 +749,8 @@ ira_build_conflicts (void) build_conflicts (); ira_traverse_loop_tree (true, ira_loop_tree_root, NULL, add_copies); /* We need finished conflict table for the subsequent call. */ - if (flag_ira_algorithm == IRA_ALGORITHM_REGIONAL - || flag_ira_algorithm == IRA_ALGORITHM_MIXED) + if (flag_ira_region == IRA_REGION_ALL + || flag_ira_region == IRA_REGION_MIXED) propagate_copies (); /* Now we can free memory for the conflict table (see function build_allocno_conflicts for details). */ @@ -759,6 +761,14 @@ ira_build_conflicts (void) } ira_free (conflicts); } + if (! CLASS_LIKELY_SPILLED_P (BASE_REG_CLASS)) + CLEAR_HARD_REG_SET (temp_hard_reg_set); + else + { + COPY_HARD_REG_SET (temp_hard_reg_set, reg_class_contents[BASE_REG_CLASS]); + AND_COMPL_HARD_REG_SET (temp_hard_reg_set, ira_no_alloc_regs); + AND_HARD_REG_SET (temp_hard_reg_set, call_used_reg_set); + } FOR_EACH_ALLOCNO (a, ai) { if (ALLOCNO_CALLS_CROSSED_NUM (a) == 0) @@ -775,9 +785,15 @@ ira_build_conflicts (void) { IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a), no_caller_save_reg_set); + IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a), + temp_hard_reg_set); if (ALLOCNO_CALLS_CROSSED_NUM (a) != 0) - IOR_HARD_REG_SET (ALLOCNO_CONFLICT_HARD_REGS (a), - no_caller_save_reg_set); + { + IOR_HARD_REG_SET (ALLOCNO_CONFLICT_HARD_REGS (a), + no_caller_save_reg_set); + IOR_HARD_REG_SET (ALLOCNO_CONFLICT_HARD_REGS (a), + temp_hard_reg_set); + } } } if (optimize && internal_flag_ira_verbose > 2 && ira_dump_file != NULL) diff --git a/gcc/ira-costs.c b/gcc/ira-costs.c index 3daeb075d3..a2df9bde9a 100644 --- a/gcc/ira-costs.c +++ b/gcc/ira-costs.c @@ -105,6 +105,9 @@ static enum reg_class *allocno_pref; /* Allocated buffers for allocno_pref. */ static enum reg_class *allocno_pref_buffer; +/* Record register class of each allocno with the same regno. */ +static enum reg_class *common_classes; + /* Execution frequency of the current insn. */ static int frequency; @@ -1082,8 +1085,8 @@ print_costs (FILE *f) { fprintf (f, " %s:%d", reg_class_names[rclass], COSTS_OF_ALLOCNO (allocno_costs, i)->cost[k]); - if (flag_ira_algorithm == IRA_ALGORITHM_REGIONAL - || flag_ira_algorithm == IRA_ALGORITHM_MIXED) + if (flag_ira_region == IRA_REGION_ALL + || flag_ira_region == IRA_REGION_MIXED) fprintf (f, ",%d", COSTS_OF_ALLOCNO (total_costs, i)->cost[k]); } } @@ -1173,7 +1176,7 @@ find_allocno_class_costs (void) int rclass, a_num, parent_a_num; ira_loop_tree_node_t parent; int best_cost, allocno_cost; - enum reg_class best, alt_class, common_class; + enum reg_class best, alt_class; #ifdef FORBIDDEN_INC_DEC_CLASSES int inc_dec_p = false; #endif @@ -1187,8 +1190,8 @@ find_allocno_class_costs (void) a = ALLOCNO_NEXT_REGNO_ALLOCNO (a)) { a_num = ALLOCNO_NUM (a); - if ((flag_ira_algorithm == IRA_ALGORITHM_REGIONAL - || flag_ira_algorithm == IRA_ALGORITHM_MIXED) + if ((flag_ira_region == IRA_REGION_ALL + || flag_ira_region == IRA_REGION_MIXED) && (parent = ALLOCNO_LOOP_TREE_NODE (a)->parent) != NULL && (parent_a = parent->regno_allocno_map[i]) != NULL /* There are no caps yet. */ @@ -1247,6 +1250,7 @@ find_allocno_class_costs (void) > reg_class_size[alt_class])) alt_class = reg_class_subunion[alt_class][rclass]; } + alt_class = ira_class_translate[alt_class]; if (pass == flag_expensive_optimizations) { if (best_cost > temp_costs->mem_cost) @@ -1260,18 +1264,22 @@ find_allocno_class_costs (void) i, reg_class_names[best], reg_class_names[alt_class]); } if (best_cost > temp_costs->mem_cost) - common_class = NO_REGS; + common_classes[i] = NO_REGS; + else if (flag_ira_algorithm == IRA_ALGORITHM_PRIORITY) + /* Make the common class the biggest class of best and + alt_class. */ + common_classes[i] = alt_class == NO_REGS ? best : alt_class; else /* Make the common class a cover class. Remember all allocnos with the same regno should have the same cover class. */ - common_class = ira_class_translate[best]; + common_classes[i] = ira_class_translate[best]; for (a = ira_regno_allocno_map[i]; a != NULL; a = ALLOCNO_NEXT_REGNO_ALLOCNO (a)) { a_num = ALLOCNO_NUM (a); - if (common_class == NO_REGS) + if (common_classes[i] == NO_REGS) best = NO_REGS; else { @@ -1283,7 +1291,7 @@ find_allocno_class_costs (void) for (k = 0; k < cost_classes_num; k++) { rclass = cost_classes[k]; - if (! ira_class_subset_p[rclass][common_class]) + if (! ira_class_subset_p[rclass][common_classes[i]]) continue; /* Ignore classes that are too small for this operand or invalid for an operand that was @@ -1319,6 +1327,8 @@ find_allocno_class_costs (void) } ALLOCNO_COVER_CLASS_COST (a) = allocno_cost; } + ira_assert (flag_ira_algorithm == IRA_ALGORITHM_PRIORITY + || ira_class_translate[best] == common_classes[i]); if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL && (pass == 0 || allocno_pref[a_num] != best)) { @@ -1330,7 +1340,7 @@ find_allocno_class_costs (void) ALLOCNO_LOOP_TREE_NODE (a)->loop->num); fprintf (ira_dump_file, ") best %s, cover %s\n", reg_class_names[best], - reg_class_names[ira_class_translate[best]]); + reg_class_names[common_classes[i]]); } allocno_pref[a_num] = best; } @@ -1439,7 +1449,7 @@ setup_allocno_cover_class_and_costs (void) { i = ALLOCNO_NUM (a); mode = ALLOCNO_MODE (a); - cover_class = ira_class_translate[allocno_pref[i]]; + cover_class = common_classes[ALLOCNO_REGNO (a)]; ira_assert (allocno_pref[i] == NO_REGS || cover_class != NO_REGS); ALLOCNO_MEMORY_COST (a) = COSTS_OF_ALLOCNO (allocno_costs, i)->mem_cost; ira_set_allocno_cover_class (a, cover_class); @@ -1572,6 +1582,9 @@ ira_costs (void) allocno_pref_buffer = (enum reg_class *) ira_allocate (sizeof (enum reg_class) * ira_allocnos_num); + common_classes + = (enum reg_class *) ira_allocate (sizeof (enum reg_class) + * max_reg_num ()); find_allocno_class_costs (); setup_allocno_cover_class_and_costs (); /* Because we could process operands only as subregs, check mode of @@ -1580,6 +1593,7 @@ ira_costs (void) if (ira_register_move_cost[ALLOCNO_MODE (a)] == NULL && have_regs_of_mode[ALLOCNO_MODE (a)]) ira_init_register_move_cost (ALLOCNO_MODE (a)); + ira_free (common_classes); ira_free (allocno_pref_buffer); ira_free (total_costs); ira_free (allocno_costs); diff --git a/gcc/ira-emit.c b/gcc/ira-emit.c index 29f3fdf6fa..536d6ee47f 100644 --- a/gcc/ira-emit.c +++ b/gcc/ira-emit.c @@ -1025,6 +1025,7 @@ void ira_emit (bool loops_p) { basic_block bb; + rtx insn; edge_iterator ei; edge e; ira_allocno_t a; @@ -1085,6 +1086,14 @@ ira_emit (bool loops_p) ira_free (allocno_last_set_check); ira_free (allocno_last_set); commit_edge_insertions (); + /* Fix insn codes. It is necessary to do it before reload because + reload assumes initial insn codes defined. The insn codes can be + invalidated by CFG infrastructure for example in jump + redirection. */ + FOR_EACH_BB (bb) + FOR_BB_INSNS_REVERSE (bb, insn) + if (INSN_P (insn)) + recog_memoized (insn); ira_free (at_bb_end); ira_free (at_bb_start); } diff --git a/gcc/ira-int.h b/gcc/ira-int.h index 5c6b355ecc..1fc6da265e 100644 --- a/gcc/ira-int.h +++ b/gcc/ira-int.h @@ -819,6 +819,16 @@ extern enum reg_class ira_class_translate[N_REG_CLASSES]; taking all hard-registers including fixed ones into account. */ extern enum reg_class ira_reg_class_intersect[N_REG_CLASSES][N_REG_CLASSES]; +/* True if the two classes (that is calculated taking only hard + registers available for allocation into account) are + intersected. */ +extern bool ira_reg_classes_intersect_p[N_REG_CLASSES][N_REG_CLASSES]; + +/* Classes with end marker LIM_REG_CLASSES which are intersected with + given class (the first index). That includes given class itself. + This is calculated taking only hard registers available for + allocation into account. */ +extern enum reg_class ira_reg_class_super_classes[N_REG_CLASSES][N_REG_CLASSES]; /* The biggest important class inside of union of the two classes (that is calculated taking only hard registers available for allocation into account). If the both classes contain no hard diff --git a/gcc/ira-lives.c b/gcc/ira-lives.c index 83b5ec85e6..c7868f39a5 100644 --- a/gcc/ira-lives.c +++ b/gcc/ira-lives.c @@ -117,18 +117,23 @@ make_regno_born (int regno) static void update_allocno_pressure_excess_length (ira_allocno_t a) { - int start; - enum reg_class cover_class; + int start, i; + enum reg_class cover_class, cl; allocno_live_range_t p; cover_class = ALLOCNO_COVER_CLASS (a); - if (high_pressure_start_point[cover_class] < 0) - return; - p = ALLOCNO_LIVE_RANGES (a); - ira_assert (p != NULL); - start = (high_pressure_start_point[cover_class] > p->start - ? high_pressure_start_point[cover_class] : p->start); - ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a) += curr_point - start + 1; + for (i = 0; + (cl = ira_reg_class_super_classes[cover_class][i]) != LIM_REG_CLASSES; + i++) + { + if (high_pressure_start_point[cl] < 0) + continue; + p = ALLOCNO_LIVE_RANGES (a); + ira_assert (p != NULL); + start = (high_pressure_start_point[cl] > p->start + ? high_pressure_start_point[cl] : p->start); + ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a) += curr_point - start + 1; + } } /* Process the death of register REGNO. This updates hard_regs_live @@ -165,8 +170,8 @@ static int curr_reg_pressure[N_REG_CLASSES]; static void set_allocno_live (ira_allocno_t a) { - int nregs; - enum reg_class cover_class; + int i; + enum reg_class cover_class, cl; /* Invalidate because it is referenced. */ allocno_saved_at_call[ALLOCNO_NUM (a)] = 0; @@ -176,15 +181,17 @@ set_allocno_live (ira_allocno_t a) IOR_HARD_REG_SET (ALLOCNO_CONFLICT_HARD_REGS (a), hard_regs_live); IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a), hard_regs_live); cover_class = ALLOCNO_COVER_CLASS (a); - nregs = ira_reg_class_nregs[cover_class][ALLOCNO_MODE (a)]; - curr_reg_pressure[cover_class] += nregs; - if (high_pressure_start_point[cover_class] < 0 - && (curr_reg_pressure[cover_class] - > ira_available_class_regs[cover_class])) - high_pressure_start_point[cover_class] = curr_point; - if (curr_bb_node->reg_pressure[cover_class] - < curr_reg_pressure[cover_class]) - curr_bb_node->reg_pressure[cover_class] = curr_reg_pressure[cover_class]; + for (i = 0; + (cl = ira_reg_class_super_classes[cover_class][i]) != LIM_REG_CLASSES; + i++) + { + curr_reg_pressure[cl] += ira_reg_class_nregs[cl][ALLOCNO_MODE (a)]; + if (high_pressure_start_point[cl] < 0 + && (curr_reg_pressure[cl] > ira_available_class_regs[cl])) + high_pressure_start_point[cl] = curr_point; + if (curr_bb_node->reg_pressure[cl] < curr_reg_pressure[cl]) + curr_bb_node->reg_pressure[cl] = curr_reg_pressure[cl]; + } } /* Mark allocno A as currently not living and update current register @@ -193,26 +200,40 @@ set_allocno_live (ira_allocno_t a) static void clear_allocno_live (ira_allocno_t a) { - unsigned int i; - enum reg_class cover_class; + int i; + unsigned int j; + enum reg_class cover_class, cl; + bool set_p; /* Invalidate because it is referenced. */ allocno_saved_at_call[ALLOCNO_NUM (a)] = 0; if (sparseset_bit_p (allocnos_live, ALLOCNO_NUM (a))) { cover_class = ALLOCNO_COVER_CLASS (a); - curr_reg_pressure[cover_class] - -= ira_reg_class_nregs[cover_class][ALLOCNO_MODE (a)]; - ira_assert (curr_reg_pressure[cover_class] >= 0); - if (high_pressure_start_point[cover_class] >= 0 - && (curr_reg_pressure[cover_class] - <= ira_available_class_regs[cover_class])) + set_p = false; + for (i = 0; + (cl = ira_reg_class_super_classes[cover_class][i]) + != LIM_REG_CLASSES; + i++) { - EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, i) - { - update_allocno_pressure_excess_length (ira_allocnos[i]); - } - high_pressure_start_point[cover_class] = -1; + curr_reg_pressure[cl] -= ira_reg_class_nregs[cl][ALLOCNO_MODE (a)]; + ira_assert (curr_reg_pressure[cl] >= 0); + if (high_pressure_start_point[cl] >= 0 + && curr_reg_pressure[cl] <= ira_available_class_regs[cl]) + set_p = true; + } + if (set_p) + { + EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, j) + update_allocno_pressure_excess_length (ira_allocnos[j]); + for (i = 0; + (cl = ira_reg_class_super_classes[cover_class][i]) + != LIM_REG_CLASSES; + i++) + if (high_pressure_start_point[cl] >= 0 + && curr_reg_pressure[cl] <= ira_available_class_regs[cl]) + high_pressure_start_point[cl] = -1; + } } sparseset_clear_bit (allocnos_live, ALLOCNO_NUM (a)); @@ -225,7 +246,7 @@ clear_allocno_live (ira_allocno_t a) static void mark_reg_live (rtx reg) { - int regno; + int i, regno; gcc_assert (REG_P (reg)); regno = REGNO (reg); @@ -249,7 +270,7 @@ mark_reg_live (rtx reg) else if (! TEST_HARD_REG_BIT (ira_no_alloc_regs, regno)) { int last = regno + hard_regno_nregs[regno][GET_MODE (reg)]; - enum reg_class cover_class; + enum reg_class cover_class, cl; while (regno < last) { @@ -257,20 +278,26 @@ mark_reg_live (rtx reg) && ! TEST_HARD_REG_BIT (eliminable_regset, regno)) { cover_class = ira_hard_regno_cover_class[regno]; - if (cover_class != NO_REGS) + for (i = 0; + (cl = ira_reg_class_super_classes[cover_class][i]) + != LIM_REG_CLASSES; + i++) { - curr_reg_pressure[cover_class]++; - if (high_pressure_start_point[cover_class] < 0 - && (curr_reg_pressure[cover_class] - > ira_available_class_regs[cover_class])) - high_pressure_start_point[cover_class] = curr_point; + curr_reg_pressure[cl]++; + if (high_pressure_start_point[cl] < 0 + && (curr_reg_pressure[cl] + > ira_available_class_regs[cl])) + high_pressure_start_point[cl] = curr_point; } make_regno_born (regno); - if (cover_class != NO_REGS - && (curr_bb_node->reg_pressure[cover_class] - < curr_reg_pressure[cover_class])) - curr_bb_node->reg_pressure[cover_class] - = curr_reg_pressure[cover_class]; + for (i = 0; + (cl = ira_reg_class_super_classes[cover_class][i]) + != LIM_REG_CLASSES; + i++) + { + if (curr_bb_node->reg_pressure[cl] < curr_reg_pressure[cl]) + curr_bb_node->reg_pressure[cl] = curr_reg_pressure[cl]; + } } regno++; } @@ -317,30 +344,41 @@ mark_reg_dead (rtx reg) } else if (! TEST_HARD_REG_BIT (ira_no_alloc_regs, regno)) { - unsigned int i; + int i; + unsigned int j; int last = regno + hard_regno_nregs[regno][GET_MODE (reg)]; - enum reg_class cover_class; + enum reg_class cover_class, cl; + bool set_p; while (regno < last) { if (TEST_HARD_REG_BIT (hard_regs_live, regno)) { + set_p = false; cover_class = ira_hard_regno_cover_class[regno]; - if (cover_class != NO_REGS) + for (i = 0; + (cl = ira_reg_class_super_classes[cover_class][i]) + != LIM_REG_CLASSES; + i++) + { + curr_reg_pressure[cl]--; + if (high_pressure_start_point[cl] >= 0 + && curr_reg_pressure[cl] <= ira_available_class_regs[cl]) + set_p = true; + ira_assert (curr_reg_pressure[cl] >= 0); + } + if (set_p) { - curr_reg_pressure[cover_class]--; - if (high_pressure_start_point[cover_class] >= 0 - && (curr_reg_pressure[cover_class] - <= ira_available_class_regs[cover_class])) - { - EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, i) - { - update_allocno_pressure_excess_length - (ira_allocnos[i]); - } - high_pressure_start_point[cover_class] = -1; - } - ira_assert (curr_reg_pressure[cover_class] >= 0); + EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, j) + update_allocno_pressure_excess_length (ira_allocnos[j]); + for (i = 0; + (cl = ira_reg_class_super_classes[cover_class][i]) + != LIM_REG_CLASSES; + i++) + if (high_pressure_start_point[cl] >= 0 + && (curr_reg_pressure[cl] + <= ira_available_class_regs[cl])) + high_pressure_start_point[cl] = -1; } make_regno_dead (regno); } @@ -807,18 +845,20 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node) for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) if (TEST_HARD_REG_BIT (hard_regs_live, i)) { - enum reg_class cover_class; + enum reg_class cover_class, cl; - cover_class = ira_hard_regno_cover_class[i]; - if (cover_class == NO_REGS) - continue; - curr_reg_pressure[cover_class]++; - if (curr_bb_node->reg_pressure[cover_class] - < curr_reg_pressure[cover_class]) - curr_bb_node->reg_pressure[cover_class] - = curr_reg_pressure[cover_class]; - ira_assert (curr_reg_pressure[cover_class] - <= ira_available_class_regs[cover_class]); + cover_class = ira_class_translate[REGNO_REG_CLASS (i)]; + for (j = 0; + (cl = ira_reg_class_super_classes[cover_class][j]) + != LIM_REG_CLASSES; + j++) + { + curr_reg_pressure[cl]++; + if (curr_bb_node->reg_pressure[cl] < curr_reg_pressure[cl]) + curr_bb_node->reg_pressure[cl] = curr_reg_pressure[cl]; + ira_assert (curr_reg_pressure[cl] + <= ira_available_class_regs[cl]); + } } EXECUTE_IF_SET_IN_BITMAP (reg_live_out, FIRST_PSEUDO_REGISTER, j, bi) { diff --git a/gcc/ira.c b/gcc/ira.c index 4b6854272f..44f7032bf3 100644 --- a/gcc/ira.c +++ b/gcc/ira.c @@ -434,6 +434,8 @@ setup_class_hard_regs (void) COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]); AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs); CLEAR_HARD_REG_SET (processed_hard_reg_set); + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + ira_class_hard_reg_index[cl][0] = -1; for (n = 0, i = 0; i < FIRST_PSEUDO_REGISTER; i++) { #ifdef REG_ALLOC_ORDER @@ -714,22 +716,72 @@ enum reg_class ira_important_classes[N_REG_CLASSES]; classes. */ int ira_important_class_nums[N_REG_CLASSES]; -/* Check IRA_COVER_CLASSES and sets the four global variables defined - above. */ +/* Set the four global variables defined above. */ static void setup_cover_and_important_classes (void) { - int i, j; + int i, j, n; + bool set_p, eq_p; enum reg_class cl; - const enum reg_class *classes; + const enum reg_class *cover_classes; HARD_REG_SET temp_hard_regset2; + static enum reg_class classes[LIM_REG_CLASSES + 1]; + + if (targetm.ira_cover_classes == NULL) + cover_classes = NULL; + else + cover_classes = targetm.ira_cover_classes (); + if (cover_classes == NULL) + ira_assert (flag_ira_algorithm == IRA_ALGORITHM_PRIORITY); + else + { + for (i = 0; (cl = cover_classes[i]) != LIM_REG_CLASSES; i++) + classes[i] = cl; + classes[i] = LIM_REG_CLASSES; + } + + if (flag_ira_algorithm == IRA_ALGORITHM_PRIORITY) + { + n = 0; + for (i = 0; i <= LIM_REG_CLASSES; i++) + { + if (i == NO_REGS) + continue; +#ifdef CONSTRAINT__LIMIT + for (j = 0; j < CONSTRAINT__LIMIT; j++) + if ((int) regclass_for_constraint (j) == i) + break; + if (j < CONSTRAINT__LIMIT) + { + classes[n++] = i; + continue; + } +#endif + COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[i]); + AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs); + for (j = 0; j < LIM_REG_CLASSES; j++) + { + if (i == j) + continue; + COPY_HARD_REG_SET (temp_hard_regset2, reg_class_contents[j]); + AND_COMPL_HARD_REG_SET (temp_hard_regset2, + no_unit_alloc_regs); + if (hard_reg_set_equal_p (temp_hard_regset, + temp_hard_regset2)) + break; + } + if (j >= i) + classes[n++] = i; + } + classes[n] = LIM_REG_CLASSES; + } - classes = targetm.ira_cover_classes (); ira_reg_class_cover_size = 0; for (i = 0; (cl = classes[i]) != LIM_REG_CLASSES; i++) { for (j = 0; j < i; j++) - if (reg_classes_intersect_p (cl, classes[j])) + if (flag_ira_algorithm != IRA_ALGORITHM_PRIORITY + && reg_classes_intersect_p (cl, classes[j])) gcc_unreachable (); COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]); AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs); @@ -742,22 +794,34 @@ setup_cover_and_important_classes (void) COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]); AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs); if (! hard_reg_set_empty_p (temp_hard_regset)) - for (j = 0; j < ira_reg_class_cover_size; j++) - { - COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]); - AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs); - COPY_HARD_REG_SET (temp_hard_regset2, - reg_class_contents[ira_reg_class_cover[j]]); - AND_COMPL_HARD_REG_SET (temp_hard_regset2, no_unit_alloc_regs); - if (cl == ira_reg_class_cover[j] - || (hard_reg_set_subset_p (temp_hard_regset, temp_hard_regset2) - && ! hard_reg_set_equal_p (temp_hard_regset, - temp_hard_regset2))) - { - ira_important_class_nums[cl] = ira_important_classes_num; - ira_important_classes[ira_important_classes_num++] = cl; - } - } + { + set_p = eq_p = false; + for (j = 0; j < ira_reg_class_cover_size; j++) + { + COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]); + AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs); + COPY_HARD_REG_SET (temp_hard_regset2, + reg_class_contents[ira_reg_class_cover[j]]); + AND_COMPL_HARD_REG_SET (temp_hard_regset2, no_unit_alloc_regs); + if (cl == ira_reg_class_cover[j]) + { + eq_p = false; + set_p = true; + break; + } + else if (hard_reg_set_equal_p (temp_hard_regset, + temp_hard_regset2)) + eq_p = true; + else if (hard_reg_set_subset_p (temp_hard_regset, + temp_hard_regset2)) + set_p = true; + } + if (set_p && ! eq_p) + { + ira_important_class_nums[cl] = ira_important_classes_num; + ira_important_classes[ira_important_classes_num++] = cl; + } + } } } @@ -776,25 +840,44 @@ setup_class_translate (void) for (cl = 0; cl < N_REG_CLASSES; cl++) ira_class_translate[cl] = NO_REGS; + + if (flag_ira_algorithm == IRA_ALGORITHM_PRIORITY) + for (cl = 0; cl < LIM_REG_CLASSES; cl++) + { + COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]); + AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs); + for (i = 0; i < ira_reg_class_cover_size; i++) + { + HARD_REG_SET temp_hard_regset2; + + cover_class = ira_reg_class_cover[i]; + COPY_HARD_REG_SET (temp_hard_regset2, + reg_class_contents[cover_class]); + AND_COMPL_HARD_REG_SET (temp_hard_regset2, no_unit_alloc_regs); + if (hard_reg_set_equal_p (temp_hard_regset, temp_hard_regset2)) + ira_class_translate[cl] = cover_class; + } + } for (i = 0; i < ira_reg_class_cover_size; i++) { cover_class = ira_reg_class_cover[i]; - for (cl_ptr = &alloc_reg_class_subclasses[cover_class][0]; - (cl = *cl_ptr) != LIM_REG_CLASSES; - cl_ptr++) - { - if (ira_class_translate[cl] == NO_REGS) - ira_class_translate[cl] = cover_class; + if (flag_ira_algorithm != IRA_ALGORITHM_PRIORITY) + for (cl_ptr = &alloc_reg_class_subclasses[cover_class][0]; + (cl = *cl_ptr) != LIM_REG_CLASSES; + cl_ptr++) + { + if (ira_class_translate[cl] == NO_REGS) + ira_class_translate[cl] = cover_class; #ifdef ENABLE_IRA_CHECKING - else - { - COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]); - AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs); - if (! hard_reg_set_empty_p (temp_hard_regset)) - gcc_unreachable (); - } + else + { + COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]); + AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs); + if (! hard_reg_set_empty_p (temp_hard_regset)) + gcc_unreachable (); + } #endif - } + } ira_class_translate[cover_class] = cover_class; } /* For classes which are not fully covered by a cover class (in @@ -842,6 +925,17 @@ setup_class_translate (void) account. */ enum reg_class ira_reg_class_intersect[N_REG_CLASSES][N_REG_CLASSES]; +/* True if the two classes (that is calculated taking only hard + registers available for allocation into account) are + intersected. */ +bool ira_reg_classes_intersect_p[N_REG_CLASSES][N_REG_CLASSES]; + +/* Important classes with end marker LIM_REG_CLASSES which are + supersets with given important class (the first index). That + includes given class itself. This is calculated taking only hard + registers available for allocation into account. */ +enum reg_class ira_reg_class_super_classes[N_REG_CLASSES][N_REG_CLASSES]; + /* The biggest important reg_class inside of union of the two reg_classes (that is calculated taking only hard registers available for allocation into account). If the both reg_classes @@ -851,17 +945,23 @@ enum reg_class ira_reg_class_intersect[N_REG_CLASSES][N_REG_CLASSES]; reg_class_subunion value. */ enum reg_class ira_reg_class_union[N_REG_CLASSES][N_REG_CLASSES]; -/* Set up IRA_REG_CLASS_INTERSECT and IRA_REG_CLASS_UNION. */ +/* Set up the above reg class relations. */ static void -setup_reg_class_intersect_union (void) +setup_reg_class_relations (void) { int i, cl1, cl2, cl3; HARD_REG_SET intersection_set, union_set, temp_set2; + bool important_class_p[N_REG_CLASSES]; + memset (important_class_p, 0, sizeof (important_class_p)); + for (i = 0; i < ira_important_classes_num; i++) + important_class_p[ira_important_classes[i]] = true; for (cl1 = 0; cl1 < N_REG_CLASSES; cl1++) { + ira_reg_class_super_classes[cl1][0] = LIM_REG_CLASSES; for (cl2 = 0; cl2 < N_REG_CLASSES; cl2++) { + ira_reg_classes_intersect_p[cl1][cl2] = false; ira_reg_class_intersect[cl1][cl2] = NO_REGS; COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl1]); AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs); @@ -882,6 +982,19 @@ setup_reg_class_intersect_union (void) ira_reg_class_union[cl1][cl2] = reg_class_subunion[cl1][cl2]; continue; } + ira_reg_classes_intersect_p[cl1][cl2] + = hard_reg_set_intersect_p (temp_hard_regset, temp_set2); + if (important_class_p[cl1] && important_class_p[cl2] + && hard_reg_set_subset_p (temp_hard_regset, temp_set2)) + { + enum reg_class *p; + + p = &ira_reg_class_super_classes[cl1][0]; + while (*p != LIM_REG_CLASSES) + p++; + *p++ = (enum reg_class) cl2; + *p = LIM_REG_CLASSES; + } ira_reg_class_union[cl1][cl2] = NO_REGS; COPY_HARD_REG_SET (intersection_set, reg_class_contents[cl1]); AND_HARD_REG_SET (intersection_set, reg_class_contents[cl2]); @@ -966,12 +1079,9 @@ static void find_reg_class_closure (void) { setup_reg_subclasses (); - if (targetm.ira_cover_classes) - { - setup_cover_and_important_classes (); - setup_class_translate (); - setup_reg_class_intersect_union (); - } + setup_cover_and_important_classes (); + setup_class_translate (); + setup_reg_class_relations (); } @@ -1804,8 +1914,8 @@ ira (FILE *f) if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL) fprintf (ira_dump_file, "Building IRA IR\n"); loops_p = ira_build (optimize - && (flag_ira_algorithm == IRA_ALGORITHM_REGIONAL - || flag_ira_algorithm == IRA_ALGORITHM_MIXED)); + && (flag_ira_region == IRA_REGION_ALL + || flag_ira_region == IRA_REGION_MIXED)); saved_flag_ira_share_spill_slots = flag_ira_share_spill_slots; if (too_high_register_pressure_p ()) diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 8781418bd8..b7885e6cf3 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -760,10 +760,10 @@ use_pointer_for_field (tree decl, omp_context *shared_ctx) omp_context *up; for (up = shared_ctx->outer; up; up = up->outer) - if (maybe_lookup_decl (decl, up)) + if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up)) break; - if (up && is_taskreg_ctx (up)) + if (up) { tree c; diff --git a/gcc/opts.c b/gcc/opts.c index a87fb498b1..42e3beeb92 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -870,9 +870,11 @@ decode_options (unsigned int argc, const char **argv) } } - /* Use IRA if it is implemented for the target. */ - if (targetm.ira_cover_classes) - flag_ira = 1; + flag_ira = 1; + /* Use priority coloring if cover classes is not defined for the + target. */ + if (targetm.ira_cover_classes == NULL) + flag_ira_algorithm = IRA_ALGORITHM_PRIORITY; /* -O1 optimizations. */ opt1 = (optimize >= 1); @@ -1096,10 +1098,12 @@ decode_options (unsigned int argc, const char **argv) if (!flag_sel_sched_pipelining) flag_sel_sched_pipelining_outer_loops = 0; - if (flag_ira && !targetm.ira_cover_classes) + if (flag_ira && !targetm.ira_cover_classes + && flag_ira_algorithm == IRA_ALGORITHM_CB) { - inform (input_location, "-fira does not work on this architecture"); - flag_ira = 0; + inform (input_location, + "-fira-algorithm=CB does not work on this architecture"); + flag_ira_algorithm = IRA_ALGORITHM_PRIORITY; } /* Save the current optimization options if this is the first call. */ @@ -1976,16 +1980,25 @@ common_handle_option (size_t scode, const char *arg, int value, break; case OPT_fira_algorithm_: - if (!strcmp (arg, "regional")) - flag_ira_algorithm = IRA_ALGORITHM_REGIONAL; - else if (!strcmp (arg, "CB")) + if (!strcmp (arg, "CB")) flag_ira_algorithm = IRA_ALGORITHM_CB; - else if (!strcmp (arg, "mixed")) - flag_ira_algorithm = IRA_ALGORITHM_MIXED; + else if (!strcmp (arg, "priority")) + flag_ira_algorithm = IRA_ALGORITHM_PRIORITY; else warning (0, "unknown ira algorithm \"%s\"", arg); break; + case OPT_fira_region_: + if (!strcmp (arg, "one")) + flag_ira_region = IRA_REGION_ONE; + else if (!strcmp (arg, "all")) + flag_ira_region = IRA_REGION_ALL; + else if (!strcmp (arg, "mixed")) + flag_ira_region = IRA_REGION_MIXED; + else + warning (0, "unknown ira region \"%s\"", arg); + break; + case OPT_fira_verbose_: flag_ira_verbose = value; break; diff --git a/gcc/predict.c b/gcc/predict.c index 73dbcbdc4c..22e71ceab8 100644 --- a/gcc/predict.c +++ b/gcc/predict.c @@ -2052,7 +2052,7 @@ estimate_bb_frequencies (void) basic_block bb; sreal freq_max; - if (cfun->function_frequency != PROFILE_READ || !counts_to_freqs ()) + if (profile_status != PROFILE_READ || !counts_to_freqs ()) { static int real_values_initialized = 0; diff --git a/gcc/reload1.c b/gcc/reload1.c index ac1e874b12..ffde2bf94d 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -6084,9 +6084,10 @@ choose_reload_regs (struct insn_chain *chain) need_mode = mode; else need_mode - = smallest_mode_for_size (GET_MODE_BITSIZE (mode) - + byte * BITS_PER_UNIT, - GET_MODE_CLASS (mode)); + = smallest_mode_for_size + (GET_MODE_BITSIZE (mode) + byte * BITS_PER_UNIT, + GET_MODE_CLASS (mode) == MODE_PARTIAL_INT + ? MODE_INT : GET_MODE_CLASS (mode)); if ((GET_MODE_SIZE (GET_MODE (last_reg)) >= GET_MODE_SIZE (need_mode)) diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index 17654611e1..0e7caa5450 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -1316,7 +1316,7 @@ compute_record_mode (tree type) However, if possible, we use a mode that fits in a register instead, in order to allow for better optimization down the line. */ - TYPE_MODE (type) = BLKmode; + SET_TYPE_MODE (type, BLKmode); if (! host_integerp (TYPE_SIZE (type), 1)) return; @@ -1360,9 +1360,9 @@ compute_record_mode (tree type) if (TREE_CODE (type) == RECORD_TYPE && mode != VOIDmode && host_integerp (TYPE_SIZE (type), 1) && GET_MODE_BITSIZE (mode) == TREE_INT_CST_LOW (TYPE_SIZE (type))) - TYPE_MODE (type) = mode; + SET_TYPE_MODE (type, mode); else - TYPE_MODE (type) = mode_for_size_tree (TYPE_SIZE (type), MODE_INT, 1); + SET_TYPE_MODE (type, mode_for_size_tree (TYPE_SIZE (type), MODE_INT, 1)); /* If structure's known alignment is less than what the scalar mode would need, and it matters, then stick with BLKmode. */ @@ -1374,7 +1374,7 @@ compute_record_mode (tree type) /* If this is the only reason this type is BLKmode, then don't force containing types to be BLKmode. */ TYPE_NO_FORCE_BLK (type) = 1; - TYPE_MODE (type) = BLKmode; + SET_TYPE_MODE (type, BLKmode); } } @@ -1458,7 +1458,7 @@ finalize_type_size (tree type) TYPE_SIZE_UNIT (variant) = size_unit; TYPE_ALIGN (variant) = align; TYPE_USER_ALIGN (variant) = user_align; - TYPE_MODE (variant) = mode; + SET_TYPE_MODE (variant, mode); } } } @@ -1580,14 +1580,15 @@ layout_type (tree type) && tree_int_cst_sgn (TYPE_MIN_VALUE (type)) >= 0) TYPE_UNSIGNED (type) = 1; - TYPE_MODE (type) = smallest_mode_for_size (TYPE_PRECISION (type), - MODE_INT); + SET_TYPE_MODE (type, + smallest_mode_for_size (TYPE_PRECISION (type), MODE_INT)); TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type))); TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE (type))); break; case REAL_TYPE: - TYPE_MODE (type) = mode_for_size (TYPE_PRECISION (type), MODE_FLOAT, 0); + SET_TYPE_MODE (type, + mode_for_size (TYPE_PRECISION (type), MODE_FLOAT, 0)); TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type))); TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE (type))); break; @@ -1600,11 +1601,11 @@ layout_type (tree type) case COMPLEX_TYPE: TYPE_UNSIGNED (type) = TYPE_UNSIGNED (TREE_TYPE (type)); - TYPE_MODE (type) - = mode_for_size (2 * TYPE_PRECISION (TREE_TYPE (type)), - (TREE_CODE (TREE_TYPE (type)) == REAL_TYPE - ? MODE_COMPLEX_FLOAT : MODE_COMPLEX_INT), - 0); + SET_TYPE_MODE (type, + mode_for_size (2 * TYPE_PRECISION (TREE_TYPE (type)), + (TREE_CODE (TREE_TYPE (type)) == REAL_TYPE + ? MODE_COMPLEX_FLOAT : MODE_COMPLEX_INT), + 0)); TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type))); TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE (type))); break; @@ -1636,10 +1637,11 @@ layout_type (tree type) else mode = MIN_MODE_VECTOR_INT; + /* Do not check vector_mode_supported_p here. We'll do that + later in vector_type_mode. */ for (; mode != VOIDmode ; mode = GET_MODE_WIDER_MODE (mode)) if (GET_MODE_NUNITS (mode) == nunits - && GET_MODE_INNER (mode) == innermode - && targetm.vector_mode_supported_p (mode)) + && GET_MODE_INNER (mode) == innermode) break; /* For integers, try mapping it to a same-sized scalar mode. */ @@ -1648,10 +1650,12 @@ layout_type (tree type) mode = mode_for_size (nunits * GET_MODE_BITSIZE (innermode), MODE_INT, 0); - if (mode == VOIDmode || !have_regs_of_mode[mode]) - TYPE_MODE (type) = BLKmode; + if (mode == VOIDmode || + (GET_MODE_CLASS (mode) == MODE_INT + && !have_regs_of_mode[mode])) + SET_TYPE_MODE (type, BLKmode); else - TYPE_MODE (type) = mode; + SET_TYPE_MODE (type, mode); } TYPE_SATURATING (type) = TYPE_SATURATING (TREE_TYPE (type)); @@ -1672,7 +1676,7 @@ layout_type (tree type) /* This is an incomplete type and so doesn't have a size. */ TYPE_ALIGN (type) = 1; TYPE_USER_ALIGN (type) = 0; - TYPE_MODE (type) = VOIDmode; + SET_TYPE_MODE (type, VOIDmode); break; case OFFSET_TYPE: @@ -1680,7 +1684,7 @@ layout_type (tree type) TYPE_SIZE_UNIT (type) = size_int (POINTER_SIZE / BITS_PER_UNIT); /* A pointer might be MODE_PARTIAL_INT, but ptrdiff_t must be integral. */ - TYPE_MODE (type) = mode_for_size (POINTER_SIZE, MODE_INT, 0); + SET_TYPE_MODE (type, mode_for_size (POINTER_SIZE, MODE_INT, 0)); break; case FUNCTION_TYPE: @@ -1688,7 +1692,7 @@ layout_type (tree type) /* It's hard to see what the mode and size of a function ought to be, but we do know the alignment is FUNCTION_BOUNDARY, so make it consistent with that. */ - TYPE_MODE (type) = mode_for_size (FUNCTION_BOUNDARY, MODE_INT, 0); + SET_TYPE_MODE (type, mode_for_size (FUNCTION_BOUNDARY, MODE_INT, 0)); TYPE_SIZE (type) = bitsize_int (FUNCTION_BOUNDARY); TYPE_SIZE_UNIT (type) = size_int (FUNCTION_BOUNDARY / BITS_PER_UNIT); break; @@ -1696,7 +1700,6 @@ layout_type (tree type) case POINTER_TYPE: case REFERENCE_TYPE: { - enum machine_mode mode = ((TREE_CODE (type) == REFERENCE_TYPE && reference_types_internal) ? Pmode : TYPE_MODE (type)); @@ -1792,7 +1795,7 @@ layout_type (tree type) fall back on structural equality. */ SET_TYPE_STRUCTURAL_EQUALITY (type); TYPE_USER_ALIGN (type) = TYPE_USER_ALIGN (element); - TYPE_MODE (type) = BLKmode; + SET_TYPE_MODE (type, BLKmode); if (TYPE_SIZE (type) != 0 #ifdef MEMBER_TYPE_FORCES_BLK && ! MEMBER_TYPE_FORCES_BLK (type, VOIDmode) @@ -1805,17 +1808,17 @@ layout_type (tree type) /* One-element arrays get the component type's mode. */ if (simple_cst_equal (TYPE_SIZE (type), TYPE_SIZE (TREE_TYPE (type)))) - TYPE_MODE (type) = TYPE_MODE (TREE_TYPE (type)); + SET_TYPE_MODE (type, TYPE_MODE (TREE_TYPE (type))); else - TYPE_MODE (type) - = mode_for_size_tree (TYPE_SIZE (type), MODE_INT, 1); + SET_TYPE_MODE (type, mode_for_size_tree (TYPE_SIZE (type), + MODE_INT, 1)); if (TYPE_MODE (type) != BLKmode && STRICT_ALIGNMENT && TYPE_ALIGN (type) < BIGGEST_ALIGNMENT && TYPE_ALIGN (type) < GET_MODE_ALIGNMENT (TYPE_MODE (type))) { TYPE_NO_FORCE_BLK (type) = 1; - TYPE_MODE (type) = BLKmode; + SET_TYPE_MODE (type, BLKmode); } } /* When the element size is constant, check that it is at least as @@ -1877,6 +1880,45 @@ layout_type (tree type) if (AGGREGATE_TYPE_P (type)) gcc_assert (!TYPE_ALIAS_SET_KNOWN_P (type)); } + +/* Vector types need to re-check the target flags each time we report + the machine mode. We need to do this because attribute target can + change the result of vector_mode_supported_p and have_regs_of_mode + on a per-function basis. Thus the TYPE_MODE of a VECTOR_TYPE can + change on a per-function basis. */ +/* ??? Possibly a better solution is to run through all the types + referenced by a function and re-compute the TYPE_MODE once, rather + than make the TYPE_MODE macro call a function. */ + +enum machine_mode +vector_type_mode (const_tree t) +{ + enum machine_mode mode; + + gcc_assert (TREE_CODE (t) == VECTOR_TYPE); + + mode = t->type.mode; + if (VECTOR_MODE_P (mode) + && (!targetm.vector_mode_supported_p (mode) + || !have_regs_of_mode[mode])) + { + enum machine_mode innermode = TREE_TYPE (t)->type.mode; + + /* For integers, try mapping it to a same-sized scalar mode. */ + if (GET_MODE_CLASS (innermode) == MODE_INT) + { + mode = mode_for_size (TYPE_VECTOR_SUBPARTS (t) + * GET_MODE_BITSIZE (innermode), MODE_INT, 0); + + if (mode != VOIDmode && have_regs_of_mode[mode]) + return mode; + } + + return BLKmode; + } + + return mode; +} /* Create and return a type for signed integers of PRECISION bits. */ @@ -1921,10 +1963,10 @@ make_fract_type (int precision, int unsignedp, int satp) if (unsignedp) { TYPE_UNSIGNED (type) = 1; - TYPE_MODE (type) = mode_for_size (precision, MODE_UFRACT, 0); + SET_TYPE_MODE (type, mode_for_size (precision, MODE_UFRACT, 0)); } else - TYPE_MODE (type) = mode_for_size (precision, MODE_FRACT, 0); + SET_TYPE_MODE (type, mode_for_size (precision, MODE_FRACT, 0)); layout_type (type); return type; @@ -1947,10 +1989,10 @@ make_accum_type (int precision, int unsignedp, int satp) if (unsignedp) { TYPE_UNSIGNED (type) = 1; - TYPE_MODE (type) = mode_for_size (precision, MODE_UACCUM, 0); + SET_TYPE_MODE (type, mode_for_size (precision, MODE_UACCUM, 0)); } else - TYPE_MODE (type) = mode_for_size (precision, MODE_ACCUM, 0); + SET_TYPE_MODE (type, mode_for_size (precision, MODE_ACCUM, 0)); layout_type (type); return type; @@ -1965,7 +2007,7 @@ initialize_sizetypes (bool signed_p) tree t = make_node (INTEGER_TYPE); int precision = GET_MODE_BITSIZE (SImode); - TYPE_MODE (t) = SImode; + SET_TYPE_MODE (t, SImode); TYPE_ALIGN (t) = GET_MODE_ALIGNMENT (SImode); TYPE_USER_ALIGN (t) = 0; TYPE_IS_SIZETYPE (t) = 1; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d7490b0025..a3c9d7c4e6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,217 @@ +2008-12-12 Daniel Franke + + PR fortran/36355 + * gfortran.dg/matmul_argument_types.f90: New. + +2008-12-11 Janis Johnson + + PR testsuite/29071 + * gcc.dg/20020919-1.c: Fix a preprocessor check. + +2008-12-11 Sebastian Pop + + PR middle-end/38413 + * gcc.dg/graphite/pr38413.c: New. + +2008-12-11 Sebastian Pop + + PR middle-end/37857 + * gfortran.dg/graphite/pr37857.f90: New. + +2008-12-11 Harsha Jagasia + + PR tree-optimization/38446 + * gcc.dg/graphite/pr38446.c: New. + +2008-12-11 Sebastian Pop + + * gcc.dg/graphite/scop-16.c: Test only scop specific info. + * gcc.dg/graphite/scop-17.c: Same. + * gcc.dg/graphite/block-5.c: New. + * gcc.dg/graphite/block-6.c: New. + * gcc.dg/graphite/pr37485.c: Clean dump file after. + * gcc.dg/graphite/pr37684.c: Same. + * gcc.dg/graphite/block-2.c: Same. + +2008-12-10 Tobias Grosser + + PR middle-end/38459 + * gfortran.dg/graphite/pr38459.f90: New. + +2008-12-11 Sebastian Pop + + PR middle-end/37852 + PR middle-end/37883 + PR middle-end/37928 + PR middle-end/37980 + PR middle-end/38038 + PR middle-end/38039 + PR middle-end/38073 + PR middle-end/38083 + PR middle-end/38125 + * gcc.dg/graphite/pr37928.c: New. + * gcc.dg/graphite/pr37883.c: New. + * gcc.dg/graphite/pr38073.c: New. + * gcc.dg/graphite/pr38125.c: New. + * gfortran.dg/graphite/pr38083.f90: New. + * gfortran.dg/graphite/pr37852.f90: New. + * gfortran.dg/graphite/pr37980.f90: New. + * gfortran.dg/graphite/id-2.f90: New. + * gfortran.dg/graphite/id-4.f90: New. + + * gcc.dg/graphite/scop-18.c: Remove reduction, test for + the number of detected scops. Copy exact same test for loop blocking... + * gcc.dg/graphite/block-1.c: Fix the number of expected loops + to be blocked as reductions are not handled. + * gcc.dg/graphite/block-4.c: ...here. New. + +2008-12-11 Ira Rosen + + PR tree-optimization/38464 + * gcc.dg/vect/costmodel/ppc/costmodel-slp-12.c: Check that three + loops are vectorized. + +2008-12-10 Jason Merrill + + PR c++/35319 + * g++.dg/ext/fixed2.C: New test. + +2008-12-10 Daniel Berlin + + PR tree-optimization/36792 + * gcc.dg/tree-ssa/ssa-fre-10.c: Update expected results. + +2008-12-10 Alexandre Oliva + + PR middle-end/38271 + * gcc.dg/torture/pr38271.c: New. + +2008-12-10 Ira Rosen + + PR tree-optimization/37416 + * gcc.dg/vect/pr36630.c: Expect 1 vectorized loop. + +2008-12-10 Uros Bizjak + + * gcc.dg/20020919-1.c: Correct target selector to alpha*-*-*. + * gcc.dg/pr31866.c: Ditto. + * gcc.dg/torture/type-generic-1.c: Add -mieee for alpha*-*-* targets. + * g++.dg/torture/type-generic-1.C: Ditto. + * gfortran.dg/boz_9.f90: Ditto. + * gfortran.dg/boz_14.f90: Ditto. + * gfortran.dg/init_flag_3.f90: Ditto. + * gfortran.dg/init_flag_4.f90: Ditto. + * gfortran.dg/init_flag_5.f90: Ditto. + * gfortran.dg/integer_exponentiation_1.f90: Ditto. + * gfortran.dg/integer_exponentiation_5.F90: Ditto. + * gfortran.dg/isnan_1.f90: Ditto. + * gfortran.dg/isnan_2.f90: Ditto. + * gfortran.dg/module_nan.f90: Ditto. + * gfortran.dg/nan_1.f90: Ditto. + * gfortran.dg/nan_2.f90: Ditto. + * gfortran.dg/nan_3.f90: Ditto. + * gfortran.dg/nan_4.f90: Ditto. + * gfortran.dg/namelist_42.f90: Ditto. + * gfortran.dg/namelist_43.f90: Ditto. + * gfortran.dg/nearest_1.f90: Ditto. + * gfortran.dg/nearest_2.f90: Ditto. + * gfortran.dg/nearest_3.f90: Ditto. + * gfortran.dg/pr37243.f: Ditto. + * gfortran.dg/real_const_3.f90: Ditto. + * gfortran.dg/transfer_simplify_2.f90: Ditto. + * gfortran.fortran-torture/execute/intrinsic_spacing.x: New file. + + * gfortran.dg/default_format_denormal_1.f90: XFAIL on alpha. + +2008-12-09 Mark Mitchell + + PR c++/37971 + * g++.dg/overload/defarg2.C: New test. + * g++.dg/overload/defarg3.C: Likewise. + +2008-12-09 Jakub Jelinek + + PR middle-end/38454 + * gcc.dg/memset-1.c: New test. + * gcc.dg/memcpy-2.c: New test. + +2008-12-09 Mikael Morin + + PR fortran/35983 + * gfortran.dg/pr35983.f90: New test. + +2008-12-09 H.J. Lu + + PR testsuite/38420 + * gcc.target/i386/pr37248-2.c: Support hex dump on 32bit host. + * gcc.target/i386/pr37248-3.c: Likewise. + +2008-12-09 Steve Ellcey + + PR testsuite/37326 + * gcc.dg/tree-ssa/ssa-store-ccp-3.c: Skip on hppa*64-*-*. + +2008-12-09 Jakub Jelinek + + PR tree-optimization/35468 + * gcc.dg/pr35468.c: New test. + * gcc.c-torture/compile/pr35468.c: New test. + +2008-12-08 Jason Merrill + + PR c++/38410 + * gcc.dg/ctor1.c: New test. + +2008-12-09 Tobias Grosser + + PR middle-end/38084 + * gfortran.dg/graphite/id-3.f90: New. + * gcc.dg/graphite/pr38084.c: New. + +2008-12-08 Uros Bizjak + + * gcc.target/mips/fix-r10000-6.c: Add dg-message to look for + the note about changed semantics of NAND builtin. + * gcc.target/mips/fix-r10000-12.c: Ditto. + * gcc.target/mips/atomic-memory-1.c: Ditto. + (main): Correct __sync_nand_and_fetch results. + +2008-12-08 Dodji Seketeli + + PR debug/38390 + * g++.dg/debug/dwarf2/imported-module-2.C: New test. + +2008-12-08 Steve Ellcey + + * g++.dg/other/packed1.C: Remove ia64-hp-hpux* XFAIL. + +2008-12-08 Steve Ellcey + + * gcc.target/ia64/versionid-1.c (dg-final): Fix syntax. + * gcc.target/ia64/versionid-2.c (dg-final): Ditto. + +2008-12-08 Jakub Jelinek + + PR c/35443 + * gcc.dg/pr35443.c: New test. + + PR c/35442 + * gcc.dg/pr35442.c: New test. + +2008-12-07 Eric Botcazou + + * gnat.dg/string_comparison.adb: New test. + +2008-12-07 H.J. Lu + + PR tree-optimization/38405 + * gcc.dg/torture/pr38405.c: New. + +2008-12-07 Eric Botcazou + + * gnat.dg/aggr10.adb: New test. + * gnat.dg/aggr10_pkg.ads: New helper. + 2008-12-06 Jerry DeLisle PR fortran/38425 @@ -1823,7 +2037,7 @@ 2008-09-24 Steve Ellcey - * gcc.dg/vect/O3-vect-pr34223.c: Check vect_int_mult. + * gcc.dg/vect/O3-vect-pr34223.c: Check vect_int_mult. 2008-09-24 Aldy Hernandez diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/imported-module-2.C b/gcc/testsuite/g++.dg/debug/dwarf2/imported-module-2.C new file mode 100644 index 0000000000..86128975b4 --- /dev/null +++ b/gcc/testsuite/g++.dg/debug/dwarf2/imported-module-2.C @@ -0,0 +1,18 @@ +// Contributed by Dodji Seketeli +// Origin: PR debug/38390 +// { dg-do compile } +// { dg-options "-g -dA" } +// { dg-final { scan-assembler "DW_TAG_imported" } } + +namespace A +{ + int v; +} + +int +f () +{ + using namespace A; + return v; +} + diff --git a/gcc/testsuite/g++.dg/ext/fixed2.C b/gcc/testsuite/g++.dg/ext/fixed2.C new file mode 100644 index 0000000000..a4766eb794 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/fixed2.C @@ -0,0 +1,7 @@ +// PR c++/35319 +// { dg-options "" } + +void foo() +{ + throw 0r; +} diff --git a/gcc/testsuite/g++.dg/other/packed1.C b/gcc/testsuite/g++.dg/other/packed1.C index 5d19eb0e2a..b1b829b223 100644 --- a/gcc/testsuite/g++.dg/other/packed1.C +++ b/gcc/testsuite/g++.dg/other/packed1.C @@ -1,4 +1,4 @@ -// { dg-do run { xfail arm-*-* sh-*-* ia64-hp-hpux* } } +// { dg-do run { xfail arm-*-* sh-*-* } } // NMS:2003-04-21 this fails on strict aligned architectures again, // the patch was reverted because it broke something more important. diff --git a/gcc/testsuite/g++.dg/overload/defarg2.C b/gcc/testsuite/g++.dg/overload/defarg2.C new file mode 100644 index 0000000000..d8ecb2fa77 --- /dev/null +++ b/gcc/testsuite/g++.dg/overload/defarg2.C @@ -0,0 +1,17 @@ +// PR c++/37971 +// { dg-do compile } + +class C { +private: + static int f(int); + static int f(char); + +public: + static void g(int (*)(int) = f); +}; + +void h() { + /* Although C::f is inaccessible here, it is accessible in the + context of C::g, so there is no error. */ + C::g(); +} diff --git a/gcc/testsuite/g++.dg/overload/defarg3.C b/gcc/testsuite/g++.dg/overload/defarg3.C new file mode 100644 index 0000000000..6622e430a6 --- /dev/null +++ b/gcc/testsuite/g++.dg/overload/defarg3.C @@ -0,0 +1,15 @@ +// PR c++/37971 +// { dg-do compile } + +class C { +private: + static int f(int); // { dg-error "private" } + static int f(char); +}; + +class D { +public: + /* C::f is inaccessible, so this is an error, even if this function + is never called. */ + static void g(int (*)(int) = C::f); // { dg-error "context" } +}; diff --git a/gcc/testsuite/g++.dg/torture/type-generic-1.C b/gcc/testsuite/g++.dg/torture/type-generic-1.C index 7db2e69d0a..e9c17c328e 100644 --- a/gcc/testsuite/g++.dg/torture/type-generic-1.C +++ b/gcc/testsuite/g++.dg/torture/type-generic-1.C @@ -2,7 +2,7 @@ without any fast-math flags. */ /* { dg-do run } */ -/* { dg-options "-mieee" { target sh*-*-* } } */ +/* { dg-options "-mieee" { target alpha*-*-* sh*-*-* } } */ /* { dg-skip-if "No Inf/NaN support" { spu-*-* } } */ #include "../../gcc.dg/tg-tests.h" diff --git a/gcc/testsuite/gcc.c-torture/compile/pr35468.c b/gcc/testsuite/gcc.c-torture/compile/pr35468.c new file mode 100644 index 0000000000..16d064b622 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr35468.c @@ -0,0 +1,7 @@ +/* PR tree-optimization/35468 */ + +void +foo (void) +{ + *(char *) "c" = 'x'; +} diff --git a/gcc/testsuite/gcc.dg/20020919-1.c b/gcc/testsuite/gcc.dg/20020919-1.c index 15519bef7b..e0fab27020 100644 --- a/gcc/testsuite/gcc.dg/20020919-1.c +++ b/gcc/testsuite/gcc.dg/20020919-1.c @@ -8,7 +8,7 @@ You must be this tall ---> fit two long longs in asm-declared registers to enter this amusement. */ -/* { dg-do compile { target alpha-*-* cris-*-* crisv32-*-* i?86-*-* mmix-*-* powerpc*-*-* rs6000-*-* x86_64-*-* } } */ +/* { dg-do compile { target alpha*-*-* cris-*-* crisv32-*-* i?86-*-* mmix-*-* powerpc*-*-* rs6000-*-* x86_64-*-* } } */ /* { dg-options "-O2" } */ /* Constructed examples; input/output (same register), output, input, and @@ -41,7 +41,7 @@ || defined (__POWERPC__) || defined (PPC) || defined (_IBMR2) # define REG1 "6" # define REG2 "7" -# ifndef __powerpc64__ +# if !defined(__powerpc64__) && !defined(__LP64__) # define REG3 "8" # define REG4 "9" # endif diff --git a/gcc/testsuite/gcc.dg/ctor1.c b/gcc/testsuite/gcc.dg/ctor1.c new file mode 100644 index 0000000000..6c1cd72cc7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/ctor1.c @@ -0,0 +1,10 @@ +/* Related to PR c++/38410. + We shouldn't write out a static variable for an all-zero aggregate + initializer. The variable named C.0 was created by + gimplify_init_constructor. */ +/* { dg-final { scan-assembler-not "C\\.0" } } */ + +int main() +{ + int a[] = { 0,0 }; +} diff --git a/gcc/testsuite/gcc.dg/graphite/block-1.c b/gcc/testsuite/gcc.dg/graphite/block-1.c index 039b974fda..857f8d54e8 100644 --- a/gcc/testsuite/gcc.dg/graphite/block-1.c +++ b/gcc/testsuite/gcc.dg/graphite/block-1.c @@ -2,6 +2,8 @@ #define MAX 8192 +void bar (void); + int main() { int i, j; @@ -9,6 +11,8 @@ int main() int A[MAX * MAX]; int B[MAX * MAX]; + bar (); + for (i = 0; i < MAX; i++) for (j = 0; j < MAX; j++) { @@ -20,6 +24,11 @@ int main() for (j = 0; j < MAX; j++) A[i*MAX + j] += B[j*MAX + i]; + bar (); + + /* FIXME: For now, reductions are not handled by the code generation + of graphite. We have to bound the scop to the above loops. */ + for(i = 0; i < MAX; i++) for(j = 0; j < MAX; j++) sum += A[i*MAX + j]; @@ -27,5 +36,5 @@ int main() return sum; } -/* { dg-final { scan-tree-dump-times "Loop blocked" 3 "graphite"} } */ +/* { dg-final { scan-tree-dump-times "Loop blocked" 2 "graphite"} } */ /* { dg-final { cleanup-tree-dump "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/block-2.c b/gcc/testsuite/gcc.dg/graphite/block-2.c new file mode 100644 index 0000000000..cf0969bac1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/graphite/block-2.c @@ -0,0 +1,32 @@ +/* { dg-options "-O2 -floop-block -fdump-tree-graphite-all" } */ + +typedef unsigned char UChar; +typedef int Int32; +typedef unsigned int UInt32; + +void fallbackSort ( UInt32* fmap, + UInt32* eclass, + Int32 nblock, + Int32 verb ) +{ + Int32 ftab[257]; + Int32 ftabCopy[256]; + Int32 H, i, j, k, l, r, cc, cc1; + Int32 nNotDone; + Int32 nBhtab; + UChar* eclass8 = (UChar*)eclass; + + if (verb >= 4) + VPrintf0 ( " bucket sorting ...\n" ); + for (i = 0; i < 257; i++) ftab[i] = 0; + for (i = 0; i < nblock; i++) ftab[eclass8[i]]++; + for (i = 0; i < 256; i++) ftabCopy[i] = ftab[i]; + for (i = 1; i < 257; i++) ftab[i] += ftab[i-1]; + + for (i = 0; i < nblock; i++) { + j = eclass8[i] + ftab [i]; + } + AssertH ( j < 256, 1005 ); +} +/* { dg-final { scan-tree-dump-times "Loop blocked" 1 "graphite" { xfail *-*-* }} } */ +/* { dg-final { cleanup-tree-dump "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/block-4.c b/gcc/testsuite/gcc.dg/graphite/block-4.c new file mode 100644 index 0000000000..4b550b4e47 --- /dev/null +++ b/gcc/testsuite/gcc.dg/graphite/block-4.c @@ -0,0 +1,26 @@ +/* { dg-options "-O2 -floop-block -fdump-tree-graphite-all" } */ + +#define N 24 +#define M 1000 + +float A[1000][1000], B[1000][1000], C[1000][1000]; + +void test (void) +{ + int i, j, k; + + /* These loops contain too few iterations for being strip-mined by 64. */ + for (i = 0; i < 24; i++) + for (j = 0; j < 24; j++) + for (k = 0; k < 24; k++) + A[i][j] = B[i][k] * C[k][j]; + + /* These loops should still be strip mined. */ + for (i = 0; i < 1000; i++) + for (j = 0; j < 1000; j++) + for (k = 0; k < 1000; k++) + A[i][j] = B[i][k] * C[k][j]; +} + +/* { dg-final { scan-tree-dump-times "Strip Mining is not profitable" 2 "graphite" } } */ +/* { dg-final { cleanup-tree-dump "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/block-5.c b/gcc/testsuite/gcc.dg/graphite/block-5.c new file mode 100644 index 0000000000..e0bd4688d3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/graphite/block-5.c @@ -0,0 +1,26 @@ +/* { dg-options "-O2 -floop-block -fdump-tree-graphite-all" } */ + +#define N 10000 +void foo (int); +int test () +{ + int a[N][N]; + int b[N][N]; + unsigned i, j; + + for (i = 0; i < N; i++) + for (j = 0; j < N; j++) + a[i][j] = i*j; + + for (j = 1; j < N; j++) + for (i = 0; i < N; i++) + a[i][j] = a[i][j-1] + b[i][j]; + + for (i = 0; i < N; i++) + for (j = 0; j < N; j++) + foo (a[i][j]); +} + +/* Interchange is legal for loops 0 and 1 of the first two SCoPs */ +/* { dg-final { scan-tree-dump-times "Interchange valid for loops 0 and 1:" 2 "graphite"} } */ +/* { dg-final { cleanup-tree-dump "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/block-6.c b/gcc/testsuite/gcc.dg/graphite/block-6.c new file mode 100644 index 0000000000..77429f1cb8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/graphite/block-6.c @@ -0,0 +1,25 @@ +/* { dg-options "-O2 -floop-block -fdump-tree-graphite-all" } */ + +#define N 10000 +void foo (int); +int test () +{ + int a[N][N]; + unsigned i, j; + + for (i = 0; i < N; i++) + for (j = 0; j < N; j++) + a[i][j] = i*j; + + for (i = 1; i < N; i++) + for (j = 1; j < (N-1) ; j++) + a[i][j] = a[i-1][j+1] * a[i-1][j+1]/2; + + for (i = 0; i < N; i++) + for (j = 0; j < N; j++) + foo (a[i][j]); +} + +/* Interchange is not legal for loops 0 and 1 of SCoP 2. */ +/* { dg-final { scan-tree-dump-times "Interchange not valid for loops 0 and 1:" 1 "graphite"} } */ +/* { dg-final { cleanup-tree-dump "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/pr37485.c b/gcc/testsuite/gcc.dg/graphite/pr37485.c index 67661910ba..cf0969bac1 100644 --- a/gcc/testsuite/gcc.dg/graphite/pr37485.c +++ b/gcc/testsuite/gcc.dg/graphite/pr37485.c @@ -29,3 +29,4 @@ void fallbackSort ( UInt32* fmap, AssertH ( j < 256, 1005 ); } /* { dg-final { scan-tree-dump-times "Loop blocked" 1 "graphite" { xfail *-*-* }} } */ +/* { dg-final { cleanup-tree-dump "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/pr37684.c b/gcc/testsuite/gcc.dg/graphite/pr37684.c index 35c32911c3..a9e6f5a4a5 100644 --- a/gcc/testsuite/gcc.dg/graphite/pr37684.c +++ b/gcc/testsuite/gcc.dg/graphite/pr37684.c @@ -63,3 +63,5 @@ int BZ2_bzCompressInit } prepare_new_block ( s ); } + +/* { dg-final { cleanup-tree-dump "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/pr37883.c b/gcc/testsuite/gcc.dg/graphite/pr37883.c new file mode 100644 index 0000000000..2ab043adce --- /dev/null +++ b/gcc/testsuite/gcc.dg/graphite/pr37883.c @@ -0,0 +1,11 @@ +/* { dg-options "-O3 -floop-block" } */ + +void test_sort() +{ + char *base; + register char c, *i, *hi; + + for (i = base; i < hi; i++) + *i++ = c; +} + diff --git a/gcc/testsuite/gcc.dg/graphite/pr37928.c b/gcc/testsuite/gcc.dg/graphite/pr37928.c new file mode 100644 index 0000000000..47ad5bce0b --- /dev/null +++ b/gcc/testsuite/gcc.dg/graphite/pr37928.c @@ -0,0 +1,33 @@ +/* { dg-options "-O3 -floop-block" } */ + +int get_state(int size, int *node, int *hash) +{ + int i=0; + while(hash[i]) + { + if(node[hash[i]] == 0) + return hash[i]-1; + i++; + if(i==5) + i=0; + } + return -1; +} + +void foo (int); + +int gate1(int size, int *node, int *hash) +{ + int i, j ; + int add_size=0; + for(i=0; itest != test) return (-2); + jump_here: + switch (tst->num) { + case 1: + return (-1); + case 2: + if (action == 0) { + } + if (action == 1) { + goto jump_here; + } + } + return 0; +} diff --git a/gcc/testsuite/gcc.dg/graphite/pr38125.c b/gcc/testsuite/gcc.dg/graphite/pr38125.c new file mode 100644 index 0000000000..780e6f643e --- /dev/null +++ b/gcc/testsuite/gcc.dg/graphite/pr38125.c @@ -0,0 +1,32 @@ +/* { dg-options "-O3 -fgraphite-identity" } */ + +typedef struct sv TEST_SV; +typedef struct av TEST_AV; +typedef struct magic TEST_MAGIC; +typedef struct xpvav TEST_XPVAV; +struct sv +{ + void* sv_any; +}; +struct av +{ + TEST_XPVAV* sv_any; +}; +struct xpvav +{ + char* xav_array; + long int xav_fill; + long int xav_max; +}; +struct magic { + TEST_SV* mg_obj; +}; +extern TEST_SV PL_sv_undef; +Perl_av_fill( register TEST_AV *av, int fill) +{ + TEST_MAGIC *mg; + int key = ((TEST_XPVAV*) (av)->sv_any)->xav_fill; + TEST_SV** ary = ((TEST_SV**)((TEST_XPVAV*) (av)->sv_any)->xav_array); + while (key < fill) + ary[++key] = &PL_sv_undef; +} diff --git a/gcc/testsuite/gcc.dg/graphite/pr38413.c b/gcc/testsuite/gcc.dg/graphite/pr38413.c new file mode 100644 index 0000000000..6c2b23a882 --- /dev/null +++ b/gcc/testsuite/gcc.dg/graphite/pr38413.c @@ -0,0 +1,14 @@ +/* { dg-options "-O2 -fgraphite-identity" } */ + +static int qsz; + +void specqsort(base, n, size, compar) + char *base; +{ + register char c, *i, *j, *lo, *hi; + qsz = size; + for (i = base, hi = base + qsz; i < hi; ) + { + *i++ = c; + } +} diff --git a/gcc/testsuite/gcc.dg/graphite/pr38446.c b/gcc/testsuite/gcc.dg/graphite/pr38446.c new file mode 100644 index 0000000000..b7b346cd98 --- /dev/null +++ b/gcc/testsuite/gcc.dg/graphite/pr38446.c @@ -0,0 +1,14 @@ +/* { dg-options "-O2 -fgraphite-identity" } */ + +void copy_data() +{ + int ****source; + int ****dest; + + int i, j, k, l; + for (i = 0; i < 10; i++) + for (k = 0; k < 2; k++) + for (l = 0; l < 65; l++) + source[i][j][k][l] = dest[i][j][k][l]; +} + diff --git a/gcc/testsuite/gcc.dg/graphite/scop-15.c b/gcc/testsuite/gcc.dg/graphite/scop-15.c index 7e24253731..9324631e2f 100644 --- a/gcc/testsuite/gcc.dg/graphite/scop-15.c +++ b/gcc/testsuite/gcc.dg/graphite/scop-15.c @@ -48,5 +48,6 @@ int longest_match(IPos cur_match) && --chain_length != 0); return best_len; } + /* { dg-final { scan-tree-dump-times "number of SCoPs: 0" 1 "graphite"} } */ /* { dg-final { cleanup-tree-dump "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/scop-16.c b/gcc/testsuite/gcc.dg/graphite/scop-16.c index 42f7b6aade..d0b32f6397 100644 --- a/gcc/testsuite/gcc.dg/graphite/scop-16.c +++ b/gcc/testsuite/gcc.dg/graphite/scop-16.c @@ -1,4 +1,5 @@ -/* { dg-options "-O2 -floop-block -fdump-tree-graphite-all" } */ +/* { dg-options "-O2 -fgraphite -fdump-tree-graphite-all" } */ + #define N 10000 void foo (int); int test () @@ -20,6 +21,5 @@ int test () foo (a[i][j]); } -/* Interchange is legal for loops 0 and 1 of the first two SCoPs */ -/* { dg-final { scan-tree-dump-times "Interchange valid for loops 0 and 1:" 2 "graphite"} } */ +/* { dg-final { scan-tree-dump-times "number of SCoPs: 2" 1 "graphite"} } */ /* { dg-final { cleanup-tree-dump "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/scop-17.c b/gcc/testsuite/gcc.dg/graphite/scop-17.c index 4c1b0ca299..c2fec3fcca 100644 --- a/gcc/testsuite/gcc.dg/graphite/scop-17.c +++ b/gcc/testsuite/gcc.dg/graphite/scop-17.c @@ -1,4 +1,5 @@ -/* { dg-options "-O2 -floop-block -fdump-tree-graphite-all" } */ +/* { dg-options "-O2 -fgraphite -fdump-tree-graphite-all" } */ + #define N 10000 void foo (int); int test () @@ -19,6 +20,5 @@ int test () foo (a[i][j]); } -/* Interchange is not legal for loops 0 and 1 of SCoP 2. */ -/* { dg-final { scan-tree-dump-times "Interchange not valid for loops 0 and 1:" 1 "graphite"} } */ +/* { dg-final { scan-tree-dump-times "number of SCoPs: 2" 1 "graphite"} } */ /* { dg-final { cleanup-tree-dump "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/scop-18.c b/gcc/testsuite/gcc.dg/graphite/scop-18.c index fe2d5f4a41..6264116e11 100644 --- a/gcc/testsuite/gcc.dg/graphite/scop-18.c +++ b/gcc/testsuite/gcc.dg/graphite/scop-18.c @@ -1,4 +1,4 @@ -/* { dg-options "-O2 -floop-block -fdump-tree-graphite-all" } */ +/* { dg-options "-O2 -fgraphite -fdump-tree-graphite-all" } */ #define N 24 #define M 1000 @@ -13,14 +13,14 @@ void test (void) for (i = 0; i < 24; i++) for (j = 0; j < 24; j++) for (k = 0; k < 24; k++) - A[i][j] += B[i][k] * C[k][j]; + A[i][j] = B[i][k] * C[k][j]; /* These loops should still be strip mined. */ for (i = 0; i < 1000; i++) for (j = 0; j < 1000; j++) for (k = 0; k < 1000; k++) - A[i][j] += B[i][k] * C[k][j]; + A[i][j] = B[i][k] * C[k][j]; } -/* { dg-final { scan-tree-dump-times "Strip Mining is not profitable" 3 "graphite" } } */ +/* { dg-final { scan-tree-dump-times "number of SCoPs: 2" 1 "graphite"} } */ /* { dg-final { cleanup-tree-dump "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/memcpy-2.c b/gcc/testsuite/gcc.dg/memcpy-2.c new file mode 100644 index 0000000000..24464abd4a --- /dev/null +++ b/gcc/testsuite/gcc.dg/memcpy-2.c @@ -0,0 +1,25 @@ +/* PR middle-end/38454 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +typedef __SIZE_TYPE__ size_t; + +extern inline __attribute__((gnu_inline, always_inline, artificial)) void * +memcpy (void *__restrict dest, const void *__restrict src, size_t len) +{ + return __builtin___memcpy_chk (dest, /* { dg-warning "will always overflow destination buffer" } */ + src, len, __builtin_object_size (dest, 0)); +} + +struct S { char buf[10]; } s; + +void +foo (void) +{ + char buf[12]; + char *p = buf + 4; + struct S *q = (struct S *) p; + memcpy (q, &s, sizeof (s)); +} + +/* { dg-final { scan-assembler "__memcpy_chk" } } */ diff --git a/gcc/testsuite/gcc.dg/memset-1.c b/gcc/testsuite/gcc.dg/memset-1.c new file mode 100644 index 0000000000..677ae91bd0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/memset-1.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +typedef __SIZE_TYPE__ size_t; + +extern void warn_memset_zero_len (void) +__attribute__((__warning__ ("memset used with constant zero length parameter;" + " this could be due to transposed parameters"))); + +extern inline __attribute__((gnu_inline, always_inline, artificial)) void * +memset (void *dest, int ch, size_t len) +{ + if (__builtin_constant_p (len) && len == 0) + { + warn_memset_zero_len (); /* { dg-warning "memset used with constant zero" } */ + return dest; + } + return __builtin_memset (dest, ch, len); +} + +char buf[10]; + +int +main (void) +{ + memset (buf, sizeof (buf), 0); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/pr31866.c b/gcc/testsuite/gcc.dg/pr31866.c index f1afd93031..4081c0e6ad 100644 --- a/gcc/testsuite/gcc.dg/pr31866.c +++ b/gcc/testsuite/gcc.dg/pr31866.c @@ -1,5 +1,5 @@ /* PR tree-optimization/31866 */ -/* { dg-do compile { target alpha-*-* cris-*-* crisv32-*-* i?86-*-* mmix-*-* powerpc*-*-* rs6000-*-* x86_64-*-* } } */ +/* { dg-do compile { target alpha*-*-* cris-*-* crisv32-*-* i?86-*-* mmix-*-* powerpc*-*-* rs6000-*-* x86_64-*-* } } */ /* { dg-options "-O2" } */ #if defined (__alpha__) diff --git a/gcc/testsuite/gcc.dg/pr35442.c b/gcc/testsuite/gcc.dg/pr35442.c new file mode 100644 index 0000000000..4f1e3cc537 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr35442.c @@ -0,0 +1,11 @@ +/* PR c/35442 */ +/* { dg-bogus "not supported by" "" { target *-*-* } 0 } */ + +typedef char A __attribute__ ((vector_size (64))); +typedef int B __attribute__ ((vector_size (64))); + +void +foo (A a) +{ + ((B) a) (); /* { dg-error "is not a function" } */ +} diff --git a/gcc/testsuite/gcc.dg/pr35443.c b/gcc/testsuite/gcc.dg/pr35443.c new file mode 100644 index 0000000000..5dfc299e79 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr35443.c @@ -0,0 +1,9 @@ +/* PR c/35443 */ +/* { dg-options "" } */ +/* { dg-bogus "not supported by" "" { target *-*-* } 0 } */ + +void +foo () +{ + ({ int i; i; })(); /* { dg-error "is not a function" } */ +} diff --git a/gcc/testsuite/gcc.dg/pr35468.c b/gcc/testsuite/gcc.dg/pr35468.c new file mode 100644 index 0000000000..085c073070 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr35468.c @@ -0,0 +1,10 @@ +/* PR tree-optimization/35468 */ +/* { dg-do compile }*/ +/* { dg-options "-O2 -fno-tree-dce" } */ + +char *const f(void) +{ + char *const line = "/dev/ptyXX"; + line[8] = 1; + return line; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr38271.c b/gcc/testsuite/gcc.dg/torture/pr38271.c new file mode 100644 index 0000000000..2c64a9b34a --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr38271.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-Wuninitialized" } */ + +struct xxx { + short a; + short b; + void *c; +}; + +void bar(struct xxx); + +void foo(struct xxx *p, int i) +{ + struct xxx s0 = *p; + struct xxx s = s0; + if (s.a) i++; + bar(s); +} diff --git a/gcc/testsuite/gcc.dg/torture/pr38405.c b/gcc/testsuite/gcc.dg/torture/pr38405.c new file mode 100644 index 0000000000..3f93445cd6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr38405.c @@ -0,0 +1,29 @@ +/* { dg-do run } */ + +extern void abort (); +extern int printf (char *__format, ...); + +struct vpiBinaryConst { + int signed_flag :1; + int sized_flag :1; +}; + +int binary_get(int code, struct vpiBinaryConst *rfp) +{ + switch (code) { + case 1: + return rfp->signed_flag ? 1 : 0; + default: + printf("error: %d not supported\n", code); + return code; + } +} + +int main(void) +{ + struct vpiBinaryConst x={1,0}; + int y=binary_get(1, &x); + if (y!=1) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/type-generic-1.c b/gcc/testsuite/gcc.dg/torture/type-generic-1.c index 9a8e9d0048..96b5d01e5f 100644 --- a/gcc/testsuite/gcc.dg/torture/type-generic-1.c +++ b/gcc/testsuite/gcc.dg/torture/type-generic-1.c @@ -2,7 +2,7 @@ without any fast-math flags. */ /* { dg-do run } */ -/* { dg-options "-mieee" { target sh*-*-* } } */ +/* { dg-options "-mieee" { target alpha*-*-* sh*-*-* } } */ /* { dg-skip-if "No Inf/NaN support" { spu-*-* } } */ #include "../tg-tests.h" diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-10.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-10.c index cfbb9c97b1..a27f2d6c02 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-10.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-10.c @@ -4,6 +4,8 @@ union loc { unsigned reg; signed offset; }; void __frame_state_for (volatile char *state_in, int x) { + /* We should move all the loads out of this loop. Right now, we only + move one. It takes two insertions because we insert a cast. */ union loc fs; int reg; for (;;) { @@ -16,5 +18,5 @@ void __frame_state_for (volatile char *state_in, int x) } } -/* { dg-final { scan-tree-dump-not "Insertions:" "pre" } } */ +/* { dg-final { scan-tree-dump "Insertions: 2" "pre" } } */ /* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-store-ccp-3.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-store-ccp-3.c index 01eb785e1c..1db56a1753 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-store-ccp-3.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-store-ccp-3.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-skip-if "" { *-*-darwin* } { "*" } { "" } } */ +/* { dg-skip-if "" { *-*-darwin* hppa*64*-*-* } { "*" } { "" } } */ /* { dg-options "-O2 -fno-common -fdump-tree-optimized" } */ const int conststaticvariable; diff --git a/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-slp-12.c b/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-slp-12.c index 752c4f6139..5eb01ebba8 100644 --- a/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-slp-12.c +++ b/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-slp-12.c @@ -114,7 +114,7 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" {target { vect_strided && vect_int_mult } } } } */ -/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" {target { vect_strided && vect_int_mult } } } } */ +/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" {target { vect_strided && vect_int_mult } } } } */ +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 3 "vect" {target { vect_strided && vect_int_mult } } } } */ /* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/pr36630.c b/gcc/testsuite/gcc.dg/vect/pr36630.c index 9d85afffb2..2253f7574b 100644 --- a/gcc/testsuite/gcc.dg/vect/pr36630.c +++ b/gcc/testsuite/gcc.dg/vect/pr36630.c @@ -13,4 +13,5 @@ foo (unsigned char *x, short y) i = i + 1; } } +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */ /* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr37248-2.c b/gcc/testsuite/gcc.target/i386/pr37248-2.c index 25fb1066fd..ed483831a5 100644 --- a/gcc/testsuite/gcc.target/i386/pr37248-2.c +++ b/gcc/testsuite/gcc.target/i386/pr37248-2.c @@ -19,5 +19,5 @@ foo (struct S x) return x.a && x.g && x.b && x.f && x.c && x.e; } -/* { dg-final { scan-tree-dump "& 3758096391\[^\n\t\]*== 3758096391" "optimized" } } */ +/* { dg-final { scan-tree-dump "& (3758096391|0x0e0000007)\[^\n\t\]*== (3758096391|0x0e0000007)" "optimized" } } */ /* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr37248-3.c b/gcc/testsuite/gcc.target/i386/pr37248-3.c index d5d2d98e8e..3b320d7055 100644 --- a/gcc/testsuite/gcc.target/i386/pr37248-3.c +++ b/gcc/testsuite/gcc.target/i386/pr37248-3.c @@ -21,5 +21,5 @@ foo (struct S x) return x.a && x.i && x.b && x.h && x.c && x.g && x.e == 131; } -/* { dg-final { scan-tree-dump "& 3766484487\[^\n\t\]*== 3758163463" "optimized" } } */ +/* { dg-final { scan-tree-dump "& (3766484487|0x0e07ffe07)\[^\n\t\]*== (3758163463|0x0e0010607)" "optimized" } } */ /* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr38240.c b/gcc/testsuite/gcc.target/i386/pr38240.c new file mode 100644 index 0000000000..6a3568754b --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr38240.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ + +typedef float V + __attribute__ ((__vector_size__ (16), __may_alias__)); + +V __attribute__((target("sse"))) f(const V *ptr) { return *ptr; } + +V g(const V *ptr) { return *ptr; } diff --git a/gcc/testsuite/gcc.target/ia64/versionid-1.c b/gcc/testsuite/gcc.target/ia64/versionid-1.c index 7a461daf90..4ee8224a7d 100644 --- a/gcc/testsuite/gcc.target/ia64/versionid-1.c +++ b/gcc/testsuite/gcc.target/ia64/versionid-1.c @@ -7,4 +7,4 @@ int bar(int i) return (foo() + 1); } -/* { dg-final { scan-assembler "alias.*foo.*foo{20040821}" } } */ +/* { dg-final { scan-assembler "alias.*foo.*foo\\\{20040821\\\}" } } */ diff --git a/gcc/testsuite/gcc.target/ia64/versionid-2.c b/gcc/testsuite/gcc.target/ia64/versionid-2.c index 5a90aed6ce..258de09113 100644 --- a/gcc/testsuite/gcc.target/ia64/versionid-2.c +++ b/gcc/testsuite/gcc.target/ia64/versionid-2.c @@ -7,4 +7,4 @@ int foo(int i) return (1); } -/* { dg-final { scan-assembler "alias.*foo.*foo{20040821}" } } */ +/* { dg-final { scan-assembler "alias.*foo.*foo\\\{20040821\\\}" } } */ diff --git a/gcc/testsuite/gcc.target/mips/atomic-memory-1.c b/gcc/testsuite/gcc.target/mips/atomic-memory-1.c index e9a95eaa4f..b2316ee646 100644 --- a/gcc/testsuite/gcc.target/mips/atomic-memory-1.c +++ b/gcc/testsuite/gcc.target/mips/atomic-memory-1.c @@ -1,4 +1,7 @@ /* { dg-do run } */ + +/* { dg-message "note: '__sync_nand_and_fetch' changed semantics in GCC 4.4" "" { target *-*-* } 0 } */ + extern void abort (void); extern void exit (int); @@ -16,9 +19,9 @@ NOMIPS16 int main () __sync_sub_and_fetch (&v, 0x7fff); if (v != 34465) abort(); - if (__sync_nand_and_fetch (&v, 0xff) != 94) + if (__sync_nand_and_fetch (&v, 0xff) != -162) abort(); - if (__sync_fetch_and_add (&v, 6) != 94) + if (__sync_fetch_and_add (&v, 262) != -162) abort(); if (v != 100) abort(); diff --git a/gcc/testsuite/gcc.target/mips/fix-r10000-12.c b/gcc/testsuite/gcc.target/mips/fix-r10000-12.c index 0381c249e4..160f9aedd3 100644 --- a/gcc/testsuite/gcc.target/mips/fix-r10000-12.c +++ b/gcc/testsuite/gcc.target/mips/fix-r10000-12.c @@ -2,6 +2,8 @@ /* { dg-mips-options "-O2 -march=mips4 -mfix-r10000" } */ /* { dg-final { scan-assembler-times "\tbeql\t" 3 } } */ +/* { dg-message "note: '__sync_nand_and_fetch' changed semantics in GCC 4.4" "" { target *-*-* } 0 } */ + NOMIPS16 int f1 (int *z) { diff --git a/gcc/testsuite/gcc.target/mips/fix-r10000-6.c b/gcc/testsuite/gcc.target/mips/fix-r10000-6.c index 275136957c..1f81e5bc66 100644 --- a/gcc/testsuite/gcc.target/mips/fix-r10000-6.c +++ b/gcc/testsuite/gcc.target/mips/fix-r10000-6.c @@ -2,6 +2,8 @@ /* { dg-mips-options "-O2 -march=mips4 -mfix-r10000" } */ /* { dg-final { scan-assembler-times "\tbeql\t" 3 } } */ +/* { dg-message "note: '__sync_fetch_and_nand' changed semantics in GCC 4.4" "" { target *-*-* } 0 } */ + NOMIPS16 int f1 (int *z) { diff --git a/gcc/testsuite/gfortran.dg/boz_14.f90 b/gcc/testsuite/gfortran.dg/boz_14.f90 index a6690ce9f9..dd7e58e7c2 100644 --- a/gcc/testsuite/gfortran.dg/boz_14.f90 +++ b/gcc/testsuite/gfortran.dg/boz_14.f90 @@ -1,4 +1,5 @@ ! { dg-do run } +! { dg-options "-mieee" { target alpha*-*-* } } ! PR fortran/36214 ! For BOZ-initialization of floats, the precision used to be wrong sometimes. diff --git a/gcc/testsuite/gfortran.dg/boz_9.f90 b/gcc/testsuite/gfortran.dg/boz_9.f90 index 1488c6dc8b..db35da0449 100644 --- a/gcc/testsuite/gfortran.dg/boz_9.f90 +++ b/gcc/testsuite/gfortran.dg/boz_9.f90 @@ -1,5 +1,6 @@ ! { dg-do run } ! { dg-options "-fno-range-check" } +! { dg-options "-fno-range-check -mieee" { target alpha*-*-* } } ! ! PR fortran/34342 ! diff --git a/gcc/testsuite/gfortran.dg/default_format_denormal_1.f90 b/gcc/testsuite/gfortran.dg/default_format_denormal_1.f90 index 181ae9d795..c4d6086594 100644 --- a/gcc/testsuite/gfortran.dg/default_format_denormal_1.f90 +++ b/gcc/testsuite/gfortran.dg/default_format_denormal_1.f90 @@ -1,4 +1,4 @@ -! { dg-do run { xfail *-*-darwin[89]* *-*-freebsd* *-*-mingw* } } +! { dg-do run { xfail alpha*-*-* *-*-darwin[89]* *-*-freebsd* *-*-mingw* } } ! Test XFAILed on these platforms because the system's printf() lacks ! proper support for denormals. ! diff --git a/gcc/testsuite/gfortran.dg/graphite/id-2.f90 b/gcc/testsuite/gfortran.dg/graphite/id-2.f90 new file mode 100644 index 0000000000..0c9f54bb97 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/graphite/id-2.f90 @@ -0,0 +1,15 @@ +! { dg-options "-O2 -fgraphite-identity" } + +module solv_cap + integer, parameter, public :: dp = selected_real_kind(5) +contains + subroutine prod0( G, X ) + real(kind=dp), intent(in out), dimension(:,:) :: X + real(kind=dp), dimension(size(X,1),size(X,2)) :: Y + X = Y + end subroutine prod0 + function Ginteg(xq1,yq1, xq2,yq2, xp,yp) result(G) + end function Ginteg + subroutine fourir(A,ntot,kconjg, E,useold) + end subroutine fourir +end module solv_cap diff --git a/gcc/testsuite/gfortran.dg/graphite/id-3.f90 b/gcc/testsuite/gfortran.dg/graphite/id-3.f90 new file mode 100644 index 0000000000..394bdf7ac1 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/graphite/id-3.f90 @@ -0,0 +1,21 @@ +! { dg-options "-O2 -fgraphite-identity" } + +subroutine gentrs (ptrst, ncls, xmin, dcls, xdont, ndon) +do icls1 = 1, ncls + prec: do + select case (isns) + case (-1) + do icls = icls1, 1, -1 + enddo + case (+1) + do icls = icls1, ncls + if (xale > rtrst (icls1, icls)) then + endif + enddo + end select + enddo prec +enddo +contains +real function genuni (jsee) +end function genuni +end subroutine gentrs diff --git a/gcc/testsuite/gfortran.dg/graphite/id-4.f90 b/gcc/testsuite/gfortran.dg/graphite/id-4.f90 new file mode 100644 index 0000000000..896d608777 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/graphite/id-4.f90 @@ -0,0 +1,34 @@ +! { dg-options "-O2 -fgraphite-identity" } + +MODULE Vcimage + CHARACTER (LEN=80), SAVE :: CARD, FIELD +END MODULE Vcimage +MODULE Vimage + LOGICAL, SAVE :: EOFF +END MODULE Vimage +SUBROUTINE READIN(PROB, TITLE, CSTOP, FCYCLE, DCYCLE, DHIST, VHIST& + & , IMAX, PHIST, DEBUG, NSTAT, STATS, MAXSTA, NCORE, PPLOT, & + & DPLOT, VPLOT, TPLOT, SLIST, D0, E0, NODES, SHEAT, GAMMA, COLD & + & , THIST, NVISC, SCREEN, WEIGHT, TSTOP, STABF) + USE Vcimage + USE Vimage + INTEGER, DIMENSION(MAXSTA) :: STATS + IF (.NOT.EOFF) THEN + IF (FIELD=='PROB' .OR. FIELD=='PROBLEM_NUMBER') THEN + CALL QSORT (STATS(1:NSTAT)) + WRITE (16, & + &'(//'' YOU HAVE REQUESTED A PRINTOUT OF THE STATION'', & + & '' ABORT''//)') + ENDIF + ENDIF +CONTAINS + RECURSIVE SUBROUTINE QSORT (LIST) + INTEGER, DIMENSION(:), INTENT(INOUT) :: LIST + INTEGER, DIMENSION(SIZE(LIST)) :: SMALLER,LARGER + IF (SIZE(LIST) > 1) THEN + LIST(NUMBER_SMALLER+1:NUMBER_SMALLER+NUMBER_EQUAL) = CHOSEN + CALL QSORT (LARGER(1:NUMBER_LARGER)) + LIST(NUMBER_SMALLER+NUMBER_EQUAL+1:) = LARGER(1:NUMBER_LARGER) + END IF + END SUBROUTINE QSORT +END SUBROUTINE READIN diff --git a/gcc/testsuite/gfortran.dg/graphite/pr37852.f90 b/gcc/testsuite/gfortran.dg/graphite/pr37852.f90 new file mode 100644 index 0000000000..50e23428f8 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/graphite/pr37852.f90 @@ -0,0 +1,13 @@ +! { dg-options "-O2 -floop-block" } + +PROGRAM TEST_FPU +CHARACTER (LEN=36) :: invert_id(1) = & + (/ 'Test1 - Gauss 2000 (101x101) inverts'/) +END PROGRAM TEST_FPU + +SUBROUTINE Gauss (a,n) +INTEGER, PARAMETER :: RK8 = SELECTED_REAL_KIND(15, 300) +REAL(RK8) :: a(n,n) +INTEGER :: ipvt(n) +a(:,ipvt) = b +END SUBROUTINE Gauss diff --git a/gcc/testsuite/gfortran.dg/graphite/pr37857.f90 b/gcc/testsuite/gfortran.dg/graphite/pr37857.f90 new file mode 100644 index 0000000000..de2d3a124e --- /dev/null +++ b/gcc/testsuite/gfortran.dg/graphite/pr37857.f90 @@ -0,0 +1,9 @@ +! { dg-options "-O2 -floop-block" } + +program superficie_proteina + integer, parameter :: LONGreal = selected_real_kind(12,90) + integer :: number_of_polypeptides, maximum_polypeptide_length + real (kind = LONGreal), dimension (:,:), allocatable :: individual_conformations + allocate (individual_conformations(-number_of_bins:0,number_of_polypeptides)) + individual_conformations = 0.0_LONGreal +end program superficie_proteina diff --git a/gcc/testsuite/gfortran.dg/graphite/pr37980.f90 b/gcc/testsuite/gfortran.dg/graphite/pr37980.f90 new file mode 100644 index 0000000000..5306aa84c9 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/graphite/pr37980.f90 @@ -0,0 +1,11 @@ +! { dg-options "-O2 -floop-block" } + +module INT_MODULE +contains + pure function spher_cartesians(in1) result(out1) + integer(kind=kind(1)) :: in1 + intent(in) :: in1 + real(kind=kind(1.0d0)), dimension(0:in1,0:in1,0:in1) :: mat0 + mat0 = 0.0d0 + end function spher_cartesians +end module INT_MODULE diff --git a/gcc/testsuite/gfortran.dg/graphite/pr38083.f90 b/gcc/testsuite/gfortran.dg/graphite/pr38083.f90 new file mode 100644 index 0000000000..834d33ab83 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/graphite/pr38083.f90 @@ -0,0 +1,16 @@ +! { dg-options "-O3 -floop-block" } + +SUBROUTINE IVSORT (IL,IH,NSEGS,IOUNIT) + INTEGER IOUNIT + + INTEGER, PARAMETER :: MAXGS = 32 + +10 IF (IL .GE. IH) GO TO 80 +20 NSEGS = (IH + IL) / 2 + IF (NSEGS .GT. MAXSGS) THEN + WRITE (IOUNIT),MAXSGS + ENDIF +80 NSEGS = NSEGS - 1 +90 IF (IH - IL .GE. 11) GO TO 20 +110 IF (IL .EQ. IH) GO TO 80 +END SUBROUTINE IVSORT diff --git a/gcc/testsuite/gfortran.dg/graphite/pr38459.f90 b/gcc/testsuite/gfortran.dg/graphite/pr38459.f90 new file mode 100644 index 0000000000..1feb6e503e --- /dev/null +++ b/gcc/testsuite/gfortran.dg/graphite/pr38459.f90 @@ -0,0 +1,14 @@ +! { dg-options "-O2 -fgraphite-identity" } +# 1 "mltfftsg.F" +# 1 "" +SUBROUTINE mltfftsg ( a, ldax, lday, b, ldbx, ldby, & + n, m) + INTEGER, PARAMETER :: dbl = SELECTED_REAL_KIND ( 14, 200 ) + +! Arguments + INTEGER, INTENT ( IN ) :: ldbx, ldby, n, m + COMPLEX ( dbl ), INTENT ( INOUT ) :: b ( ldbx, ldby ) + + B(N+1:LDBX,1:M) = CMPLX(0._dbl,0._dbl,dbl) + +END SUBROUTINE mltfftsg diff --git a/gcc/testsuite/gfortran.dg/init_flag_3.f90 b/gcc/testsuite/gfortran.dg/init_flag_3.f90 index 7d6ab33cfc..9724d39c21 100644 --- a/gcc/testsuite/gfortran.dg/init_flag_3.f90 +++ b/gcc/testsuite/gfortran.dg/init_flag_3.f90 @@ -1,6 +1,6 @@ ! { dg-do run } ! { dg-options "-finit-integer=-1 -finit-logical=false -finit-real=nan" } -! { dg-options "-mieee -finit-integer=-1 -finit-logical=false -finit-real=nan" { target sh*-*-* } } +! { dg-options "-finit-integer=-1 -finit-logical=false -finit-real=nan -mieee" { target alpha*-*-* sh*-*-* } } program init_flag_3 call real_test diff --git a/gcc/testsuite/gfortran.dg/init_flag_4.f90 b/gcc/testsuite/gfortran.dg/init_flag_4.f90 index 8ec40bc8fa..8e1265e934 100644 --- a/gcc/testsuite/gfortran.dg/init_flag_4.f90 +++ b/gcc/testsuite/gfortran.dg/init_flag_4.f90 @@ -1,5 +1,6 @@ ! { dg-do run } ! { dg-options "-finit-real=inf" } +! { dg-options "-finit-real=inf -mieee" { target alpha*-*-* } } */ program init_flag_4 call real_test diff --git a/gcc/testsuite/gfortran.dg/init_flag_5.f90 b/gcc/testsuite/gfortran.dg/init_flag_5.f90 index 51dbd16cfb..5531251b00 100644 --- a/gcc/testsuite/gfortran.dg/init_flag_5.f90 +++ b/gcc/testsuite/gfortran.dg/init_flag_5.f90 @@ -1,5 +1,6 @@ ! { dg-do run } ! { dg-options "-finit-real=-inf" } +! { dg-options "-finit-real=-inf -mieee" { target alpha*-*-* } } */ program init_flag_5 call real_test diff --git a/gcc/testsuite/gfortran.dg/integer_exponentiation_1.f90 b/gcc/testsuite/gfortran.dg/integer_exponentiation_1.f90 index bed7c6ab02..77ef84c2e9 100644 --- a/gcc/testsuite/gfortran.dg/integer_exponentiation_1.f90 +++ b/gcc/testsuite/gfortran.dg/integer_exponentiation_1.f90 @@ -1,4 +1,5 @@ ! { dg-do run } +! { dg-options "-pedantic -mieee" { target alpha*-*-* } } ! PR 30981 - this used to go into an endless loop during execution. program test a = 3.0 diff --git a/gcc/testsuite/gfortran.dg/integer_exponentiation_5.F90 b/gcc/testsuite/gfortran.dg/integer_exponentiation_5.F90 index 07127c6aa4..2fc8df35c3 100644 --- a/gcc/testsuite/gfortran.dg/integer_exponentiation_5.F90 +++ b/gcc/testsuite/gfortran.dg/integer_exponentiation_5.F90 @@ -1,5 +1,6 @@ ! { dg-do run } ! { dg-options "-fno-range-check" } +! { dg-options "-fno-range-check -mieee" { target alpha*-*-* } } */ module mod_check implicit none diff --git a/gcc/testsuite/gfortran.dg/isnan_1.f90 b/gcc/testsuite/gfortran.dg/isnan_1.f90 index db8f5695cd..3c0cce8d37 100644 --- a/gcc/testsuite/gfortran.dg/isnan_1.f90 +++ b/gcc/testsuite/gfortran.dg/isnan_1.f90 @@ -1,7 +1,7 @@ ! Test for the ISNAN intrinsic ! ! { dg-do run } -! { dg-options "-pedantic-errors -mieee" { target sh*-*-* } } +! { dg-options "-pedantic-errors -mieee" { target alpha*-*-* sh*-*-* } } ! implicit none real :: x diff --git a/gcc/testsuite/gfortran.dg/isnan_2.f90 b/gcc/testsuite/gfortran.dg/isnan_2.f90 index e16ce9de10..37b53633fa 100644 --- a/gcc/testsuite/gfortran.dg/isnan_2.f90 +++ b/gcc/testsuite/gfortran.dg/isnan_2.f90 @@ -2,7 +2,7 @@ ! ! { dg-do run } ! { dg-options "-fno-range-check" } -! { dg-options "-fno-range-check -pedantic-errors -mieee" { target sh*-*-* } } +! { dg-options "-fno-range-check -pedantic-errors -mieee" { target alpha*-*-* sh*-*-* } } ! implicit none character(len=1) :: s diff --git a/gcc/testsuite/gfortran.dg/matmul_argument_types.f90 b/gcc/testsuite/gfortran.dg/matmul_argument_types.f90 new file mode 100644 index 0000000000..1480655c4c --- /dev/null +++ b/gcc/testsuite/gfortran.dg/matmul_argument_types.f90 @@ -0,0 +1,32 @@ +! { dg-do compile } +! +! PR fortran/36355 +! Check MATMUL argument types: +! +! numeric logical other +! numeric 1 2 3 +! logical 2 1 3 +! other 3 3 3 +! +! where +! 1 ok +! 2 argument type mismatch +! 3 invalid argument types +! + + INTEGER :: a(2,2) + LOGICAL :: b(2,2) + CHARACTER :: c + + a = MATMUL(a, a) ! ok + a = MATMUL(a, b) ! { dg-error "must match" } + a = MATMUL(a, c) ! { dg-error "must be numeric or LOGICAL" } + + b = MATMUL(b, a) ! { dg-error "must match" } + b = MATMUL(b, b) ! ok + b = MATMUL(b, c) ! { dg-error "must be numeric or LOGICAL" } + + c = MATMUL(c, a) ! { dg-error "must be numeric or LOGICAL" } + c = MATMUL(c, b) ! { dg-error "must be numeric or LOGICAL" } + c = MATMUL(c, c) ! { dg-error "must be numeric or LOGICAL" } +END diff --git a/gcc/testsuite/gfortran.dg/module_nan.f90 b/gcc/testsuite/gfortran.dg/module_nan.f90 index 956b90c49d..52fa8a9f77 100644 --- a/gcc/testsuite/gfortran.dg/module_nan.f90 +++ b/gcc/testsuite/gfortran.dg/module_nan.f90 @@ -1,6 +1,6 @@ ! { dg-do run } ! { dg-options "-fno-range-check" } -! { dg-options "-fno-range-check -mieee" { target sh*-*-* } } +! { dg-options "-fno-range-check -mieee" { target alpha*-*-* sh*-*-* } } ! ! PR fortran/34318 ! diff --git a/gcc/testsuite/gfortran.dg/namelist_42.f90 b/gcc/testsuite/gfortran.dg/namelist_42.f90 index 55dd2caec5..1aa75ab4b4 100644 --- a/gcc/testsuite/gfortran.dg/namelist_42.f90 +++ b/gcc/testsuite/gfortran.dg/namelist_42.f90 @@ -1,5 +1,5 @@ ! { dg-do run { target fd_truncate } } -! { dg-options "-mieee" { target sh*-*-* } } +! { dg-options "-mieee" { target alpha*-*-* sh*-*-* } } ! ! PR fortran/34427 ! diff --git a/gcc/testsuite/gfortran.dg/namelist_43.f90 b/gcc/testsuite/gfortran.dg/namelist_43.f90 index abad355b9a..ad518dd126 100644 --- a/gcc/testsuite/gfortran.dg/namelist_43.f90 +++ b/gcc/testsuite/gfortran.dg/namelist_43.f90 @@ -1,5 +1,5 @@ ! { dg-do run { target fd_truncate } } -! { dg-options "-mieee" { target sh*-*-* } } +! { dg-options "-mieee" { target alpha*-*-* sh*-*-* } } ! ! PR fortran/34427 ! diff --git a/gcc/testsuite/gfortran.dg/nan_1.f90 b/gcc/testsuite/gfortran.dg/nan_1.f90 index 0c9eb0435c..6b7e19f806 100644 --- a/gcc/testsuite/gfortran.dg/nan_1.f90 +++ b/gcc/testsuite/gfortran.dg/nan_1.f90 @@ -2,7 +2,7 @@ ! as arguments ! ! { dg-do run } -! { dg-options "-pedantic-errors -mieee" { target sh*-*-* } } +! { dg-options "-pedantic-errors -mieee" { target alpha*-*-* sh*-*-* } } ! module aux2 interface isnan diff --git a/gcc/testsuite/gfortran.dg/nan_2.f90 b/gcc/testsuite/gfortran.dg/nan_2.f90 index 49e1c39610..30987715f3 100644 --- a/gcc/testsuite/gfortran.dg/nan_2.f90 +++ b/gcc/testsuite/gfortran.dg/nan_2.f90 @@ -1,6 +1,6 @@ ! { dg-do run } ! { dg-options "-fno-range-check -pedantic" } -! { dg-options "-fno-range-check -pedantic -mieee" { target sh*-*-* } } +! { dg-options "-fno-range-check -pedantic -mieee" { target alpha*-*-* sh*-*-* } } ! ! PR fortran/34333 ! diff --git a/gcc/testsuite/gfortran.dg/nan_3.f90 b/gcc/testsuite/gfortran.dg/nan_3.f90 index 957b94d214..adc927674b 100644 --- a/gcc/testsuite/gfortran.dg/nan_3.f90 +++ b/gcc/testsuite/gfortran.dg/nan_3.f90 @@ -1,6 +1,6 @@ ! { dg-do run } ! { dg-options "-fno-range-check" } -! { dg-options "-fno-range-check -mieee" { target sh*-*-* } } +! { dg-options "-fno-range-check -mieee" { target alpha*-*-* sh*-*-* } } ! ! PR fortran/34319 ! diff --git a/gcc/testsuite/gfortran.dg/nan_4.f90 b/gcc/testsuite/gfortran.dg/nan_4.f90 index 771aad02fa..7c37671efe 100644 --- a/gcc/testsuite/gfortran.dg/nan_4.f90 +++ b/gcc/testsuite/gfortran.dg/nan_4.f90 @@ -1,6 +1,6 @@ ! { dg-do compile } ! { dg-options "-std=gnu" } -! { dg-options "-std=gnu -mieee" { target sh*-*-* } } +! { dg-options "-std=gnu -mieee" { target alpha*-*-* sh*-*-* } } ! ! PR fortran/34398. ! diff --git a/gcc/testsuite/gfortran.dg/nearest_1.f90 b/gcc/testsuite/gfortran.dg/nearest_1.f90 index c80f3a6bc2..64e2b8524f 100644 --- a/gcc/testsuite/gfortran.dg/nearest_1.f90 +++ b/gcc/testsuite/gfortran.dg/nearest_1.f90 @@ -1,5 +1,6 @@ ! { dg-do run } ! { dg-options "-O0 -ffloat-store" } +! { dg-options "-O0 -ffloat-store -mieee" { target alpha*-*-* } } ! PR fortran/27021 ! Original code submitted by Dominique d'Humieres ! Converted to Dejagnu for the testsuite by Steven G. Kargl diff --git a/gcc/testsuite/gfortran.dg/nearest_2.f90 b/gcc/testsuite/gfortran.dg/nearest_2.f90 index 08c774469c..8bb4768701 100644 --- a/gcc/testsuite/gfortran.dg/nearest_2.f90 +++ b/gcc/testsuite/gfortran.dg/nearest_2.f90 @@ -1,6 +1,6 @@ ! { dg-do run } ! { dg-options "-fno-range-check" } -! { dg-options "-fno-range-check -mieee" { target sh*-*-* } } +! { dg-options "-fno-range-check -mieee" { target alpha*-*-* sh*-*-* } } ! ! PR fortran/34192 ! diff --git a/gcc/testsuite/gfortran.dg/nearest_3.f90 b/gcc/testsuite/gfortran.dg/nearest_3.f90 index 4262a8cb06..3af4cfc34d 100644 --- a/gcc/testsuite/gfortran.dg/nearest_3.f90 +++ b/gcc/testsuite/gfortran.dg/nearest_3.f90 @@ -1,5 +1,5 @@ ! { dg-do run } -! { dg-options "-pedantic-errors -mieee" { target sh*-*-* } } +! { dg-options "-pedantic-errors -mieee" { target alpha*-*-* sh*-*-* } } ! ! PR fortran/34209 ! diff --git a/gcc/testsuite/gfortran.dg/pr35983.f90 b/gcc/testsuite/gfortran.dg/pr35983.f90 new file mode 100644 index 0000000000..5cc3855029 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr35983.f90 @@ -0,0 +1,24 @@ +! { dg-do run } +! +! PR fortran/35983 +! C_LOC expanded to a NULL_PTR expr if called from a structure constructor +! +! Contributed by François-Xavier Coudert + +program main + use ISO_C_BINDING + implicit none + type, bind(C) :: descr + type(C_PTR) :: address + end type descr + type(descr) :: DD + double precision, target :: buf(1) + integer (C_INTPTR_T) :: i, j + + buf = (/ 0 /) + DD = descr(c_loc(buf)) + i = transfer (DD%address, 0_c_intptr_t) + j = transfer (c_loc(buf), 0_c_intptr_t) + if (any((/ i,j /) == 0_c_intptr_t)) call abort + if (i /= j) call abort +end program main diff --git a/gcc/testsuite/gfortran.dg/pr37243.f b/gcc/testsuite/gfortran.dg/pr37243.f index 143800c5e7..ba65212255 100644 --- a/gcc/testsuite/gfortran.dg/pr37243.f +++ b/gcc/testsuite/gfortran.dg/pr37243.f @@ -1,5 +1,6 @@ ! PR rtl-optimization/37243 ! { dg-do run } +! { dg-options "-mieee" { target alpha*-*-* } } ! Check if register allocator handles IR flattening correctly. SUBROUTINE SCHMD(V,M,N,LDV) IMPLICIT DOUBLE PRECISION(A-H,O-Z) diff --git a/gcc/testsuite/gfortran.dg/real_const_3.f90 b/gcc/testsuite/gfortran.dg/real_const_3.f90 index a05986fcb8..90e82087bb 100644 --- a/gcc/testsuite/gfortran.dg/real_const_3.f90 +++ b/gcc/testsuite/gfortran.dg/real_const_3.f90 @@ -1,6 +1,6 @@ !{ dg-do run } !{ dg-options "-fno-range-check" } -!{ dg-options "-fno-range-check -mieee" { target sh*-*-* } } +!{ dg-options "-fno-range-check -mieee" { target alpha*-*-* sh*-*-* } } ! PR19310 and PR19904, allow disabling range check during compile. ! Contributed by Jerry DeLisle program main diff --git a/gcc/testsuite/gfortran.dg/transfer_simplify_2.f90 b/gcc/testsuite/gfortran.dg/transfer_simplify_2.f90 index 96bf283f03..dbad84e1ae 100644 --- a/gcc/testsuite/gfortran.dg/transfer_simplify_2.f90 +++ b/gcc/testsuite/gfortran.dg/transfer_simplify_2.f90 @@ -1,5 +1,6 @@ ! { dg-do run } ! { dg-options "-O2" } +! { dg-options "-O2 -mieee" { target alpha*-*-* } } ! Tests the fix for the meta-bug PR31237 (TRANSFER intrinsic) ! Exercises gfc_simplify_transfer a random walk through types and shapes ! and compares its results with the middle-end version that operates on diff --git a/gcc/testsuite/gfortran.fortran-torture/execute/intrinsic_spacing.x b/gcc/testsuite/gfortran.fortran-torture/execute/intrinsic_spacing.x new file mode 100644 index 0000000000..dad399dcb8 --- /dev/null +++ b/gcc/testsuite/gfortran.fortran-torture/execute/intrinsic_spacing.x @@ -0,0 +1,2 @@ +add-ieee-options +return 0 diff --git a/gcc/testsuite/gnat.dg/aggr10.adb b/gcc/testsuite/gnat.dg/aggr10.adb new file mode 100644 index 0000000000..6fbb8ed5d7 --- /dev/null +++ b/gcc/testsuite/gnat.dg/aggr10.adb @@ -0,0 +1,23 @@ +-- { dg-do compile } +-- { dg-options "-O2" } + +with Aggr10_Pkg; use Aggr10_Pkg; + +procedure Aggr10 is + + No_Name_Location : constant Name_Location := + (Name => Name_Id'First, + Location => Int'First, + Source => Source_Id'First, + Except => False, + Found => False); + + Name_Loc : Name_Location; + +begin + Name_Loc := Get; + if Name_Loc = No_Name_Location then -- { dg-bogus "comparison always false" } + raise Program_Error; + end if; + Set (Name_Loc); +end; diff --git a/gcc/testsuite/gnat.dg/aggr10_pkg.ads b/gcc/testsuite/gnat.dg/aggr10_pkg.ads new file mode 100644 index 0000000000..92400f990e --- /dev/null +++ b/gcc/testsuite/gnat.dg/aggr10_pkg.ads @@ -0,0 +1,18 @@ +package Aggr10_Pkg is + + type Name_Id is range 300_000_000 .. 399_999_999; + type Int is range -2 ** 31 .. +2 ** 31 - 1; + type Source_Id is range 5_000_000 .. 5_999_999; + + type Name_Location is record + Name : Name_Id; + Location : Int; + Source : Source_Id; + Except : Boolean; + Found : Boolean := False; + end record; + + function Get return Name_Location; + procedure Set (Name_Loc : Name_Location); + +end Aggr10_Pkg; diff --git a/gcc/testsuite/gnat.dg/string_comparison.adb b/gcc/testsuite/gnat.dg/string_comparison.adb new file mode 100644 index 0000000000..22e6c9e01b --- /dev/null +++ b/gcc/testsuite/gnat.dg/string_comparison.adb @@ -0,0 +1,10 @@ +-- { dg-do compile } + +with Ada.Text_IO; use Ada.Text_IO; + +procedure String_Comparison is + package Bool_IO is new Enumeration_IO (Boolean); + use Bool_IO; +begin + Put (Boolean'Image (True) = "True"); +end; diff --git a/gcc/toplev.c b/gcc/toplev.c index 42ad2a48fd..8417cfed6c 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -271,9 +271,11 @@ int flag_next_runtime = 0; enum tls_model flag_tls_default = TLS_MODEL_GLOBAL_DYNAMIC; -/* Set the default algorithm for the integrated register allocator. */ +/* Set the default region and algorithm for the integrated register + allocator. */ -enum ira_algorithm flag_ira_algorithm = IRA_ALGORITHM_MIXED; +enum ira_algorithm flag_ira_algorithm = IRA_ALGORITHM_CB; +enum ira_region flag_ira_region = IRA_REGION_MIXED; /* Set the default value for -fira-verbose. */ diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 28ee8ef40c..89621f0a80 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -2072,14 +2072,9 @@ struct gimple_opt_pass pass_remove_useless_stmts = static void remove_phi_nodes_and_edges_for_unreachable_block (basic_block bb) { - gimple_stmt_iterator gsi; - /* Since this block is no longer reachable, we can just delete all of its PHI nodes. */ - for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); ) - remove_phi_node (&gsi, true); - - set_phi_nodes (bb, NULL); + remove_phi_nodes (bb); /* Remove edges to BB's successors. */ while (EDGE_COUNT (bb->succs) > 0) diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h index 6004978416..d4e0004d83 100644 --- a/gcc/tree-flow.h +++ b/gcc/tree-flow.h @@ -787,6 +787,7 @@ extern gimple create_phi_node (tree, basic_block); extern void add_phi_arg (gimple, tree, edge); extern void remove_phi_args (edge); extern void remove_phi_node (gimple_stmt_iterator *, bool); +extern void remove_phi_nodes (basic_block); extern void init_phinodes (void); extern void fini_phinodes (void); extern void release_phi_node (gimple); @@ -988,6 +989,7 @@ unsigned int tree_ssa_prefetch_arrays (void); unsigned int remove_empty_loops (void); void tree_ssa_iv_optimize (void); unsigned tree_predictive_commoning (void); +tree canonicalize_loop_ivs (struct loop *, htab_t, tree); bool parallelize_loops (void); bool loop_only_exit_p (const struct loop *, const_edge); diff --git a/gcc/tree-optimize.c b/gcc/tree-optimize.c index ba3d0fcc9e..0802e5af82 100644 --- a/gcc/tree-optimize.c +++ b/gcc/tree-optimize.c @@ -293,6 +293,7 @@ execute_fixup_cfg (void) int todo = gimple_in_ssa_p (cfun) ? TODO_verify_ssa : 0; cfun->after_inlining = true; + cfun->always_inline_functions_inlined = true; if (cfun->eh) FOR_EACH_BB (bb) diff --git a/gcc/tree-parloops.c b/gcc/tree-parloops.c index d6e94b3c6a..91ce890755 100644 --- a/gcc/tree-parloops.c +++ b/gcc/tree-parloops.c @@ -1325,9 +1325,10 @@ create_loop_fn (void) /* Bases all the induction variables in LOOP on a single induction variable (unsigned with base 0 and step 1), whose final value is compared with NIT. The induction variable is incremented in the loop latch. - REDUCTION_LIST describes the reductions in LOOP. */ + REDUCTION_LIST describes the reductions in LOOP. Return the induction + variable that was created. */ -static void +tree canonicalize_loop_ivs (struct loop *loop, htab_t reduction_list, tree nit) { unsigned precision = TYPE_PRECISION (TREE_TYPE (nit)); @@ -1368,7 +1369,12 @@ canonicalize_loop_ivs (struct loop *loop, htab_t reduction_list, tree nit) } ok = simple_iv (loop, phi, res, &iv, true); - red = reduction_phi (reduction_list, phi); + + if (reduction_list) + red = reduction_phi (reduction_list, phi); + else + red = NULL; + /* We preserve the reduction phi nodes. */ if (!ok && red) { @@ -1406,6 +1412,9 @@ canonicalize_loop_ivs (struct loop *loop, htab_t reduction_list, tree nit) gimple_cond_set_code (stmt, LT_EXPR); gimple_cond_set_lhs (stmt, var_before); gimple_cond_set_rhs (stmt, nit); + update_stmt (stmt); + + return var_before; } /* Moves the exit condition of LOOP to the beginning of its header, and diff --git a/gcc/tree-phinodes.c b/gcc/tree-phinodes.c index 7fd5a8f30c..fd6ac3a511 100644 --- a/gcc/tree-phinodes.c +++ b/gcc/tree-phinodes.c @@ -474,4 +474,17 @@ remove_phi_node (gimple_stmt_iterator *gsi, bool release_lhs_p) release_ssa_name (gimple_phi_result (phi)); } +/* Remove all the phi nodes from BB. */ + +void +remove_phi_nodes (basic_block bb) +{ + gimple_stmt_iterator gsi; + + for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); ) + remove_phi_node (&gsi, true); + + set_phi_nodes (bb, NULL); +} + #include "gt-tree-phinodes.h" diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c index 51bbd4bcdc..e3d60e98b2 100644 --- a/gcc/tree-scalar-evolution.c +++ b/gcc/tree-scalar-evolution.c @@ -1229,6 +1229,18 @@ follow_ssa_edge_in_rhs (struct loop *loop, gimple stmt, case GIMPLE_SINGLE_RHS: return follow_ssa_edge_expr (loop, stmt, gimple_assign_rhs1 (stmt), halting_phi, evolution_of_loop, limit); + case GIMPLE_UNARY_RHS: + if (code == NOP_EXPR) + { + /* This assignment is under the form "a_1 = (cast) rhs. */ + t_bool res + = follow_ssa_edge_expr (loop, stmt, gimple_assign_rhs1 (stmt), + halting_phi, evolution_of_loop, limit); + *evolution_of_loop = chrec_convert (type, *evolution_of_loop, stmt); + return res; + } + /* FALLTHRU */ + default: return t_false; } diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index 8cada85409..01c0e121e0 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -2354,14 +2354,17 @@ sra_build_bf_assignment (tree dst, tree src) tmp = var; if (!is_gimple_variable (tmp)) tmp = unshare_expr (var); + else + TREE_NO_WARNING (var) = true; tmp2 = make_rename_temp (utype, "SR"); if (INTEGRAL_TYPE_P (TREE_TYPE (var))) - stmt = gimple_build_assign (tmp2, fold_convert (utype, tmp)); + tmp = fold_convert (utype, tmp); else - stmt = gimple_build_assign (tmp2, fold_build1 (VIEW_CONVERT_EXPR, - utype, tmp)); + tmp = fold_build1 (VIEW_CONVERT_EXPR, utype, tmp); + + stmt = gimple_build_assign (tmp2, tmp); gimple_seq_add_stmt (&seq, stmt); } else @@ -3223,12 +3226,20 @@ scalarize_use (struct sra_elt *elt, tree *expr_p, gimple_stmt_iterator *gsi, if (!elt->use_block_copy) { tree type = TREE_TYPE (bfexpr); - tree var, vpos; + tree var = make_rename_temp (type, "SR"), tmp, vpos; + gimple st = NULL; - if (!TYPE_UNSIGNED (type)) - type = unsigned_type_for (type); + gimple_assign_set_rhs1 (stmt, var); + update = true; - var = make_rename_temp (type, "SR"); + if (!TYPE_UNSIGNED (type)) + { + type = unsigned_type_for (type); + tmp = make_rename_temp (type, "SR"); + st = gimple_build_assign (var, + fold_convert (TREE_TYPE (var), tmp)); + var = tmp; + } gimple_seq_add_stmt (&seq, gimple_build_assign @@ -3245,8 +3256,8 @@ scalarize_use (struct sra_elt *elt, tree *expr_p, gimple_stmt_iterator *gsi, sra_explode_bitfield_assignment (var, vpos, true, &seq, blen, bpos, elt); - gimple_assign_set_rhs1 (stmt, var); - update = true; + if (st) + gimple_seq_add_stmt (&seq, st); } else sra_sync_for_bitfield_assignment diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c index 82933f8191..0908d546f0 100644 --- a/gcc/tree-ssa-ccp.c +++ b/gcc/tree-ssa-ccp.c @@ -2191,6 +2191,9 @@ fold_stmt_r (tree *expr_p, int *walk_subtrees, void *data) t = maybe_fold_stmt_indirect (expr, TREE_OPERAND (expr, 0), integer_zero_node); + /* Avoid folding *"abc" = 5 into 'a' = 5. */ + if (wi->is_lhs && t && TREE_CODE (t) == INTEGER_CST) + t = NULL_TREE; if (!t && TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR) /* If we had a good reason for propagating the address here, @@ -2219,8 +2222,10 @@ fold_stmt_r (tree *expr_p, int *walk_subtrees, void *data) Otherwise we'd be wasting time. */ case ARRAY_REF: /* If we are not processing expressions found within an - ADDR_EXPR, then we can fold constant array references. */ - if (!*inside_addr_expr_p) + ADDR_EXPR, then we can fold constant array references. + Don't fold on LHS either, to avoid folding "abc"[0] = 5 + into 'a' = 5. */ + if (!*inside_addr_expr_p && !wi->is_lhs) t = fold_read_from_constant_string (expr); else t = NULL; diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c index aa0472ea36..683d7d4b5f 100644 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@ -4355,7 +4355,12 @@ iv_ca_add_use (struct ivopts_data *data, struct iv_ca *ivs, static comp_cost iv_ca_cost (struct iv_ca *ivs) { - return (ivs->bad_uses ? infinite_cost : ivs->cost); + /* This was a conditional expression but it triggered a bug in the + Solaris 8 compiler. */ + if (ivs->bad_uses) + return infinite_cost; + else + return ivs->cost; } /* Returns true if all dependences of CP are among invariants in IVS. */ diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c index 7773fe96b6..2fb4710d86 100644 --- a/gcc/tree-ssa-pre.c +++ b/gcc/tree-ssa-pre.c @@ -3644,10 +3644,7 @@ compute_avail (void) add_to_value (get_expr_value_id (e), e); if (!in_fre) - { - bitmap_insert_into_set (TMP_GEN (block), e); - bitmap_value_insert_into_set (maximal_set, e); - } + bitmap_insert_into_set (TMP_GEN (block), e); bitmap_value_insert_into_set (AVAIL_OUT (block), e); } @@ -3716,6 +3713,7 @@ compute_avail (void) if (is_exception_related (stmt)) continue; case tcc_binary: + case tcc_comparison: { vn_nary_op_t nary; unsigned int i; diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index 46781b8212..3d64c1cbd3 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -4704,8 +4704,9 @@ static bool have_alias_info = false; /* Emit a note for the pointer initialization point DEF. */ static void -emit_pointer_definition (gimple def) +emit_pointer_definition (tree ptr, bitmap visited) { + gimple def = SSA_NAME_DEF_STMT (ptr); if (gimple_code (def) == GIMPLE_PHI) { use_operand_p argp; @@ -4715,7 +4716,10 @@ emit_pointer_definition (gimple def) { tree arg = USE_FROM_PTR (argp); if (TREE_CODE (arg) == SSA_NAME) - emit_pointer_definition (SSA_NAME_DEF_STMT (arg)); + { + if (bitmap_set_bit (visited, SSA_NAME_VERSION (arg))) + emit_pointer_definition (arg, visited); + } else inform (0, "initialized from %qE", arg); } @@ -4729,7 +4733,6 @@ emit_pointer_definition (gimple def) static void emit_alias_warning (tree ptr) { - gimple def = SSA_NAME_DEF_STMT (ptr); gimple use; imm_use_iterator ui; unsigned warned = 0; @@ -4777,7 +4780,11 @@ emit_alias_warning (tree ptr) } } if (warned > 0) - emit_pointer_definition (def); + { + bitmap visited = BITMAP_ALLOC (NULL); + emit_pointer_definition (ptr, visited); + BITMAP_FREE (visited); + } } /* Given a pointer variable P, fill in its points-to set, or return diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 1289c49ef1..9d23b24087 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -2557,11 +2557,11 @@ extract_range_from_binary_expr (value_range_t *vr, ior_max.high = vr0_max.high | vr1_max.high; if (ior_max.high != 0) { - ior_max.low = ~0u; + ior_max.low = ~(unsigned HOST_WIDE_INT)0u; ior_max.high |= ((HOST_WIDE_INT) 1 << floor_log2 (ior_max.high)) - 1; } - else + else if (ior_max.low != 0) ior_max.low |= ((unsigned HOST_WIDE_INT) 1u << floor_log2 (ior_max.low)) - 1; @@ -6512,6 +6512,12 @@ simplify_truth_ops_using_ranges (gimple_stmt_iterator *gsi, gimple stmt) !useless_type_conversion_p (TREE_TYPE (gimple_assign_lhs (stmt)), TREE_TYPE (op0)); + /* Make sure to not sign-extend -1 as a boolean value. */ + if (need_conversion + && !TYPE_UNSIGNED (TREE_TYPE (op0)) + && TYPE_PRECISION (TREE_TYPE (op0)) == 1) + return false; + switch (rhs_code) { case TRUTH_AND_EXPR: diff --git a/gcc/tree.c b/gcc/tree.c index e74b779212..03c54cc1cb 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -5522,7 +5522,7 @@ build_pointer_type_for_mode (tree to_type, enum machine_mode mode, t = make_node (POINTER_TYPE); TREE_TYPE (t) = to_type; - TYPE_MODE (t) = mode; + SET_TYPE_MODE (t, mode); TYPE_REF_CAN_ALIAS_ALL (t) = can_alias_all; TYPE_NEXT_PTR_TO (t) = TYPE_POINTER_TO (to_type); TYPE_POINTER_TO (to_type) = t; @@ -5586,7 +5586,7 @@ build_reference_type_for_mode (tree to_type, enum machine_mode mode, t = make_node (REFERENCE_TYPE); TREE_TYPE (t) = to_type; - TYPE_MODE (t) = mode; + SET_TYPE_MODE (t, mode); TYPE_REF_CAN_ALIAS_ALL (t) = can_alias_all; TYPE_NEXT_REF_TO (t) = TYPE_REFERENCE_TO (to_type); TYPE_REFERENCE_TO (to_type) = t; @@ -5655,7 +5655,7 @@ build_index_type (tree maxval) TYPE_PRECISION (itype) = TYPE_PRECISION (sizetype); TYPE_MIN_VALUE (itype) = size_zero_node; TYPE_MAX_VALUE (itype) = fold_convert (sizetype, maxval); - TYPE_MODE (itype) = TYPE_MODE (sizetype); + SET_TYPE_MODE (itype, TYPE_MODE (sizetype)); TYPE_SIZE (itype) = TYPE_SIZE (sizetype); TYPE_SIZE_UNIT (itype) = TYPE_SIZE_UNIT (sizetype); TYPE_ALIGN (itype) = TYPE_ALIGN (sizetype); @@ -5711,7 +5711,7 @@ build_range_type (tree type, tree lowval, tree highval) TYPE_MAX_VALUE (itype) = highval ? fold_convert (type, highval) : NULL; TYPE_PRECISION (itype) = TYPE_PRECISION (type); - TYPE_MODE (itype) = TYPE_MODE (type); + SET_TYPE_MODE (itype, TYPE_MODE (type)); TYPE_SIZE (itype) = TYPE_SIZE (type); TYPE_SIZE_UNIT (itype) = TYPE_SIZE_UNIT (type); TYPE_ALIGN (itype) = TYPE_ALIGN (type); @@ -7296,7 +7296,7 @@ make_vector_type (tree innertype, int nunits, enum machine_mode mode) t = make_node (VECTOR_TYPE); TREE_TYPE (t) = TYPE_MAIN_VARIANT (innertype); SET_TYPE_VECTOR_SUBPARTS (t, nunits); - TYPE_MODE (t) = mode; + SET_TYPE_MODE (t, mode); TYPE_READONLY (t) = TYPE_READONLY (innertype); TYPE_VOLATILE (t) = TYPE_VOLATILE (innertype); @@ -7553,19 +7553,19 @@ build_common_tree_nodes_2 (int short_double) dfloat32_type_node = make_node (REAL_TYPE); TYPE_PRECISION (dfloat32_type_node) = DECIMAL32_TYPE_SIZE; layout_type (dfloat32_type_node); - TYPE_MODE (dfloat32_type_node) = SDmode; + SET_TYPE_MODE (dfloat32_type_node, SDmode); dfloat32_ptr_type_node = build_pointer_type (dfloat32_type_node); dfloat64_type_node = make_node (REAL_TYPE); TYPE_PRECISION (dfloat64_type_node) = DECIMAL64_TYPE_SIZE; layout_type (dfloat64_type_node); - TYPE_MODE (dfloat64_type_node) = DDmode; + SET_TYPE_MODE (dfloat64_type_node, DDmode); dfloat64_ptr_type_node = build_pointer_type (dfloat64_type_node); dfloat128_type_node = make_node (REAL_TYPE); TYPE_PRECISION (dfloat128_type_node) = DECIMAL128_TYPE_SIZE; layout_type (dfloat128_type_node); - TYPE_MODE (dfloat128_type_node) = TDmode; + SET_TYPE_MODE (dfloat128_type_node, TDmode); dfloat128_ptr_type_node = build_pointer_type (dfloat128_type_node); complex_integer_type_node = build_complex_type (integer_type_node); diff --git a/gcc/tree.h b/gcc/tree.h index d85918fae1..55163b6c1b 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -2050,7 +2050,6 @@ struct tree_block GTY(()) #define TYPE_UID(NODE) (TYPE_CHECK (NODE)->type.uid) #define TYPE_SIZE(NODE) (TYPE_CHECK (NODE)->type.size) #define TYPE_SIZE_UNIT(NODE) (TYPE_CHECK (NODE)->type.size_unit) -#define TYPE_MODE(NODE) (TYPE_CHECK (NODE)->type.mode) #define TYPE_VALUES(NODE) (ENUMERAL_TYPE_CHECK (NODE)->type.values) #define TYPE_DOMAIN(NODE) (ARRAY_TYPE_CHECK (NODE)->type.values) #define TYPE_FIELDS(NODE) (RECORD_OR_UNION_CHECK (NODE)->type.values) @@ -2078,6 +2077,14 @@ struct tree_block GTY(()) #define TYPE_MAIN_VARIANT(NODE) (TYPE_CHECK (NODE)->type.main_variant) #define TYPE_CONTEXT(NODE) (TYPE_CHECK (NODE)->type.context) +/* Vector types need to check target flags to determine type. */ +extern enum machine_mode vector_type_mode (const_tree); +#define TYPE_MODE(NODE) \ + (TREE_CODE (TYPE_CHECK (NODE)) == VECTOR_TYPE \ + ? vector_type_mode (NODE) : (NODE)->type.mode) +#define SET_TYPE_MODE(NODE, MODE) \ + (TYPE_CHECK (NODE)->type.mode = (MODE)) + /* The "canonical" type for this type node, which can be used to compare the type for equality with another type. If two types are equal (based on the semantics of the language), then they will have diff --git a/include/ChangeLog b/include/ChangeLog index 73892f542a..be1afad278 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,27 +1,8 @@ 2008-12-10 Jason Merrill - * demangle.h (enum demangle_component_type): Add + * demangle.h (enum demangle_component_type): Add DEMANGLE_COMPONENT_FIXED_TYPE. -2008-12-01 Cary Coutant - - * plugin-api.h (ld_plugin_message): Change format parameter to const. - -2008-12-01 Cary Coutant - - * plugin-api.h: Fix syntax error when compiling with C++. - -2008-11-26 Alan Modra - - PR 7047 - * bfdlink.h (struct bfd_elf_version_expr): Delete "symbol". - Add "literal". - -2008-11-21 Sterling Augustine - - * xtensa-isa-internal.h (XTENSA_STATE_IS_SHARED_OR): New flag. - * xtensa-isa.h (xtensa_state_is_shared_or): New prototype. - 2008-11-19 Bob Wilson * xtensa-config.h (XCHAL_HAVE_MUL16, XCHAL_HAVE_MUL32, XCHAL_HAVE_DIV32) diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index 9f6148edc1..a6378bc339 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,9 @@ +2008-12-10 Alexandre Oliva + + PR target/37033 + * pch.c (cpp_valid_state): Improve message for poisoned symbols. + Allow for differences in __GCC_HAVE_DWARF2_CFI_ASM. + 2008-11-29 Joseph Myers * lex.c (cpp_token_len): Use 6 as default length. diff --git a/libcpp/pch.c b/libcpp/pch.c index bf7b9bea36..f459d2cb90 100644 --- a/libcpp/pch.c +++ b/libcpp/pch.c @@ -1,5 +1,5 @@ /* Part of CPP library. (Precompiled header reading/writing.) - Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 + Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2008 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it @@ -477,11 +477,32 @@ cpp_valid_state (cpp_reader *r, const char *name, int fd) h = cpp_lookup (r, namebuf, m.name_length); if (m.flags & NODE_POISONED - || h->type != NT_MACRO || h->flags & NODE_POISONED) { if (CPP_OPTION (r, warn_invalid_pch)) cpp_error (r, CPP_DL_WARNING_SYSHDR, + "%s: not used because `%.*s' is poisoned", + name, m.name_length, namebuf); + goto fail; + } + + if (h->type != NT_MACRO) + { + /* It's ok if __GCC_HAVE_DWARF2_CFI_ASM becomes undefined, + as in, when the PCH file is created with -g and we're + attempting to use it without -g. Restoring the PCH file + is supposed to bring in this definition *and* enable the + generation of call frame information, so that precompiled + definitions that take this macro into accout, to decide + what asm to emit, won't issue .cfi directives when the + compiler doesn't. */ + if (!(h->flags & NODE_USED) + && m.name_length == sizeof ("__GCC_HAVE_DWARF2_CFI_ASM") - 1 + && !memcmp (namebuf, "__GCC_HAVE_DWARF2_CFI_ASM", m.name_length)) + continue; + + if (CPP_OPTION (r, warn_invalid_pch)) + cpp_error (r, CPP_DL_WARNING_SYSHDR, "%s: not used because `%.*s' not defined", name, m.name_length, namebuf); goto fail; diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog index 765bbd78b3..dcc4867882 100644 --- a/libgfortran/ChangeLog +++ b/libgfortran/ChangeLog @@ -1,3 +1,12 @@ +2008-12-08 Jerry DeLisle + + PR libfortran/38430 + * io/transfer.c (data_transfer_init): Move constraint check for REC= + and STREAM access into condition for other REC= constraints to simplify. + Comment out this constraint to avoid breaking compatibility with 4.3 + until later. Added a TODO for above comment and this one. + Fix test for max pos. + 2008-12-06 Jerry DeLisle PR libfortran/38291 diff --git a/libgfortran/io/transfer.c b/libgfortran/io/transfer.c index 318d2215ee..ea63a0daff 100644 --- a/libgfortran/io/transfer.c +++ b/libgfortran/io/transfer.c @@ -1986,15 +1986,6 @@ data_transfer_init (st_parameter_dt *dtp, int read_flag) return; } - if (dtp->u.p.current_unit->flags.access == ACCESS_STREAM - && (cf & IOPARM_DT_HAS_REC) != 0) - { - generate_error (&dtp->common, LIBERROR_OPTION_CONFLICT, - "Record number not allowed for stream access " - "data transfer"); - return; - } - /* Process the ADVANCE option. */ dtp->u.p.advance_status @@ -2141,7 +2132,7 @@ data_transfer_init (st_parameter_dt *dtp, int read_flag) return; } - if (dtp->rec >= dtp->u.p.current_unit->maxrec) + if (dtp->pos >= dtp->u.p.current_unit->maxrec) { generate_error (&dtp->common, LIBERROR_BAD_OPTION, "POS=specifier too large"); @@ -2231,10 +2222,20 @@ data_transfer_init (st_parameter_dt *dtp, int read_flag) return; } - /* This is required to maintain compatibility between - 4.3 and 4.4 runtime. */ + /* TODO: This is required to maintain compatibility between + 4.3 and 4.4 runtime. Remove when ABI changes from 4.3 */ + if (is_stream_io (dtp)) dtp->u.p.current_unit->strm_pos = dtp->rec; + + /* TODO: Un-comment this code when ABI changes from 4.3. + if (dtp->u.p.current_unit->flags.access == ACCESS_STREAM) + { + generate_error (&dtp->common, LIBERROR_OPTION_CONFLICT, + "Record number not allowed for stream access " + "data transfer"); + return; + } */ } diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog index 46536c8838..98a307314a 100644 --- a/libgomp/ChangeLog +++ b/libgomp/ChangeLog @@ -1,3 +1,10 @@ +2008-12-08 Jakub Jelinek + + PR middle-end/36802 + * testsuite/libgomp.c/pr36802-1.c: New test. + * testsuite/libgomp.c/pr36802-2.c: New test. + * testsuite/libgomp.c/pr36802-3.c: New test. + 2008-12-01 Janis Johnson PR libgomp/38270 diff --git a/libgomp/testsuite/libgomp.c/pr36802-1.c b/libgomp/testsuite/libgomp.c/pr36802-1.c new file mode 100644 index 0000000000..4ed5e12769 --- /dev/null +++ b/libgomp/testsuite/libgomp.c/pr36802-1.c @@ -0,0 +1,34 @@ +/* PR middle-end/36802 */ + +extern void abort (void); + +int +foo (int k) +{ + int i = 0; +#pragma omp parallel + #pragma omp single + { + if (!k) + { + int j; + for (j = 0; j < 10; j++) + #pragma omp task + if (j == 4) + i++; + } + else + i++; + } + return i; +} + +int +main (void) +{ + if (foo (0) != 1) + abort (); + if (foo (1) != 1) + abort (); + return 0; +} diff --git a/libgomp/testsuite/libgomp.c/pr36802-2.c b/libgomp/testsuite/libgomp.c/pr36802-2.c new file mode 100644 index 0000000000..06e792f0f1 --- /dev/null +++ b/libgomp/testsuite/libgomp.c/pr36802-2.c @@ -0,0 +1,46 @@ +/* PR middle-end/36802 */ + +extern void abort (void); + +int q; + +int +foo (int k) +{ + int i = 6, n = 0; + omp_set_dynamic (0); + omp_set_nested (1); +#pragma omp parallel shared (i) num_threads (3) + { + int l; + + if (omp_get_num_threads () != 3) + #pragma omp atomic + n += 1; + else + #pragma omp for + for (l = 0; l < 3; l++) + if (k) + #pragma omp atomic + q += i; + else + #pragma omp parallel shared (i) num_threads (4) + { + if (omp_get_num_threads () != 4) + #pragma omp atomic + n += 1; + #pragma omp critical + i += 1; + } + } + if (n == 0 && i != 6 + 3 * 4) + abort (); + return 0; +} + +int +main (void) +{ + foo (0); + return 0; +} diff --git a/libgomp/testsuite/libgomp.c/pr36802-3.c b/libgomp/testsuite/libgomp.c/pr36802-3.c new file mode 100644 index 0000000000..f11baa09f5 --- /dev/null +++ b/libgomp/testsuite/libgomp.c/pr36802-3.c @@ -0,0 +1,46 @@ +/* PR middle-end/36802 */ + +extern void abort (void); + +int q; + +int +foo (int k) +{ + int i = 6, n = 0; + omp_set_dynamic (0); + omp_set_nested (1); +#pragma omp parallel shared (i) num_threads (3) + { + int l; + + if (omp_get_num_threads () != 3) + #pragma omp atomic + n += 1; + else + #pragma omp for + for (l = 0; l < 3; l++) + if (!k) + #pragma omp parallel shared (i) num_threads (4) + { + if (omp_get_num_threads () != 4) + #pragma omp atomic + n += 1; + #pragma omp critical + i += 1; + } + else + #pragma omp atomic + q += i; + } + if (n == 0 && i != 6 + 3 * 4) + abort (); + return 0; +} + +int +main (void) +{ + foo (0); + return 0; +} diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 005ef71715..e090ae9603 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,7 +1,13 @@ +2008-12-11 H.J. Lu + + PR libgcj/38006 + * classpath/tools/resource/gnu/classpath/tools/gjdoc/htmldoclet/inherit.png: + Set svn:mime-type to application/octet-stream. + 2008-12-04 Jack Howarth - * configure.ac: Add double brackets on darwin[912]. - * configure: Regenerate. + * configure.ac: Add double brackets on darwin[912]. + * configure: Regenerate. 2008-12-02 Jack Howarth diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 7bcae27edb..4070761116 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,20 @@ +2008-12-11 Jakub Jelinek + + PR c++/37582 + * testsuite/26_numerics/headers/cmath/37582.cc: New. + +2008-12-08 Paolo Carlini + + * include/tr1_impl/cmath: Undef remquof / remquol too; add using + declarations. + * acinclude.m4 [GLIBCXX_CHECK_C99_TR1]: Check remquof / remquol too. + * testsuite/tr1/8_c_compatibility/cmath/functions.cc: Adjust. + * configure: Regenerate. + +2008-12-08 Edward Smith-Rowland <3dw4rd@verizon.net> + + * include/bits/forward_list.h: Fixed spurious "forward_swap" in doxy. + 2008-12-06 Paolo Carlini PR libstdc++/38421 diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4 index bec563f0b4..f4a83460aa 100644 --- a/libstdc++-v3/acinclude.m4 +++ b/libstdc++-v3/acinclude.m4 @@ -1523,8 +1523,8 @@ AC_DEFUN([GLIBCXX_CHECK_C99_TR1], [ remainderf(0.0f, 0.0f); remainderl(0.0l, 0.0l); remquo(0.0, 0.0, 0); - remquo(0.0f, 0.0f, 0); - remquo(0.0l, 0.0l, 0); + remquof(0.0f, 0.0f, 0); + remquol(0.0l, 0.0l, 0); rint(0.0); rintf(0.0f); rintl(0.0l); diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure index c344b4c3b8..23b050032d 100644 --- a/libstdc++-v3/configure +++ b/libstdc++-v3/configure @@ -1075,10 +1075,10 @@ Optional Packages: --with-pic try to use only PIC/non-PIC objects [default=use both] --with-gnu-ld assume the C compiler uses GNU ld [default=no] - --with-system-libunwind use installed libunwind --with-gnu-ld assume the C compiler uses GNU ld default=no --with-libiconv-prefix[=DIR] search for libiconv in DIR/include and DIR/lib --without-libiconv-prefix don't search for libiconv in includedir and libdir + --with-system-libunwind use installed libunwind --with-gxx-include-dir=DIR installation directory for include files @@ -20965,8 +20965,8 @@ typedef double_t my_double_t; remainderf(0.0f, 0.0f); remainderl(0.0l, 0.0l); remquo(0.0, 0.0, 0); - remquo(0.0f, 0.0f, 0); - remquo(0.0l, 0.0l, 0); + remquof(0.0f, 0.0f, 0); + remquol(0.0l, 0.0l, 0); rint(0.0); rintf(0.0f); rintl(0.0l); @@ -41961,40 +41961,6 @@ _ACEOF fi - # For _Unwind_GetIPInfo. - - -# Check whether --with-system-libunwind or --without-system-libunwind was given. -if test "${with_system_libunwind+set}" = set; then - withval="$with_system_libunwind" - -fi; - # If system-libunwind was not specifically set, pick a default setting. - if test x$with_system_libunwind = x; then - case ${target} in - ia64-*-hpux*) with_system_libunwind=yes ;; - *) with_system_libunwind=no ;; - esac - fi - # Based on system-libunwind and target, do we have ipinfo? - if test x$with_system_libunwind = xyes; then - case ${target} in - ia64-*-*) have_unwind_getipinfo=no ;; - *) have_unwind_getipinfo=yes ;; - esac - else - have_unwind_getipinfo=yes - fi - - if test x$have_unwind_getipinfo = xyes; then - -cat >>confdefs.h <<\_ACEOF -#define HAVE_GETIPINFO 1 -_ACEOF - - fi - - # For iconv support. if test "X$prefix" = "XNONE"; then @@ -104361,13 +104327,42 @@ _ACEOF _ACEOF fi +fi + +# Check for _Unwind_GetIPInfo. - # Assume we have _Unwind_GetIPInfo for cross-compiles. - cat >>confdefs.h <<\_ACEOF + +# Check whether --with-system-libunwind or --without-system-libunwind was given. +if test "${with_system_libunwind+set}" = set; then + withval="$with_system_libunwind" + +fi; + # If system-libunwind was not specifically set, pick a default setting. + if test x$with_system_libunwind = x; then + case ${target} in + ia64-*-hpux*) with_system_libunwind=yes ;; + *) with_system_libunwind=no ;; + esac + fi + # Based on system-libunwind and target, do we have ipinfo? + if test x$with_system_libunwind = xyes; then + case ${target} in + ia64-*-*) have_unwind_getipinfo=no ;; + *) have_unwind_getipinfo=yes ;; + esac + else + have_unwind_getipinfo=yes + fi + + if test x$have_unwind_getipinfo = xyes; then + +cat >>confdefs.h <<\_ACEOF #define HAVE_GETIPINFO 1 _ACEOF -fi + fi + + # Check whether --enable-linux-futex or --disable-linux-futex was given. if test "${enable_linux_futex+set}" = set; then diff --git a/libstdc++-v3/include/bits/forward_list.h b/libstdc++-v3/include/bits/forward_list.h index cb7397800c..473982c7e7 100644 --- a/libstdc++-v3/include/bits/forward_list.h +++ b/libstdc++-v3/include/bits/forward_list.h @@ -1311,21 +1311,21 @@ _GLIBCXX_BEGIN_NAMESPACE(std) const forward_list<_Tp, _Alloc>& __ly) { return !(__ly < __lx); } - /// See std::forward_list::forward_swap(). + /// See std::forward_list::swap(). template inline void swap(forward_list<_Tp, _Alloc>& __lx, forward_list<_Tp, _Alloc>& __ly) { __lx.swap(__ly); } - /// See std::forward_list::forward_swap(). + /// See std::forward_list::swap(). template inline void swap(forward_list<_Tp, _Alloc>&& __lx, forward_list<_Tp, _Alloc>& __ly) { __lx.swap(__ly); } - /// See std::forward_list::forward_swap(). + /// See std::forward_list::swap(). template inline void swap(forward_list<_Tp, _Alloc>& __lx, diff --git a/libstdc++-v3/include/tr1_impl/cmath b/libstdc++-v3/include/tr1_impl/cmath index d969a8fead..044d122e8a 100644 --- a/libstdc++-v3/include/tr1_impl/cmath +++ b/libstdc++-v3/include/tr1_impl/cmath @@ -119,8 +119,8 @@ #undef remainderf #undef remainderl #undef remquo -#undef remquo -#undef remquo +#undef remquof +#undef remquol #undef rint #undef rintf #undef rintl @@ -266,8 +266,8 @@ _GLIBCXX_BEGIN_NAMESPACE_TR1 using ::remainderl; using ::remquo; - using ::remquo; - using ::remquo; + using ::remquof; + using ::remquol; using ::rint; using ::rintf; diff --git a/libstdc++-v3/testsuite/26_numerics/headers/cmath/37582.cc b/libstdc++-v3/testsuite/26_numerics/headers/cmath/37582.cc new file mode 100644 index 0000000000..33c9070a77 --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/headers/cmath/37582.cc @@ -0,0 +1,44 @@ +// Copyright (C) 2008 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// { dg-do compile } + +#include + +struct foo +{ + foo (double); +}; + +bool operator &&(int, const foo &); + +// libstdc++/37582 +double +test01(double x) +{ + return std::pow (x, 2.0); +} diff --git a/libstdc++-v3/testsuite/tr1/8_c_compatibility/cmath/functions.cc b/libstdc++-v3/testsuite/tr1/8_c_compatibility/cmath/functions.cc index 3bb6d9d8bf..6bbb1489d5 100644 --- a/libstdc++-v3/testsuite/tr1/8_c_compatibility/cmath/functions.cc +++ b/libstdc++-v3/testsuite/tr1/8_c_compatibility/cmath/functions.cc @@ -2,7 +2,7 @@ // 2006-02-07 Paolo Carlini // -// Copyright (C) 2006 Free Software Foundation, Inc. +// Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the @@ -156,8 +156,8 @@ void test01() ldret = std::tr1::remainderl(ld0, ld0); ret = std::tr1::remquo(d0, d0, pquo); - fret = std::tr1::remquo(f0, f0, pquo); - ldret = std::tr1::remquo(ld0, ld0, pquo); + fret = std::tr1::remquof(f0, f0, pquo); + ldret = std::tr1::remquol(ld0, ld0, pquo); ret = std::tr1::rint(d0); fret = std::tr1::rintf(f0);