+2008-12-08 Luis Machado <luisgpm@br.ibm.com>
+
+ * MAINTAINERS: Add myself to the write after approval list.
+
2008-12-04 Jack Howarth <howarth@bromo.med.uc.edu>
* configure.ac: Add double brackets on darwin[912].
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
+2008-12-12 Dwarakanath Rajagopal <dwarak.rajagopal@amd.com>
+
+ * 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 <hongjiu.lu@intel.com>
+
+ PR target/38402
+ * gcc/doc/md.texi: Remove Y and document Yz, Y2, Yi and Ym
+ constraints for x86.
+
+2008-12-12 Andreas Schwab <schwab@suse.de>
+
+ * cfgrtl.c (rtl_verify_flow_info_1): Don't apply BLOCK_FOR_INSN on
+ a BARRIER insn.
+
+2008-12-12 Uros Bizjak <ubizjak@gmail.com>
+
+ * 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 <aoliva@redhat.com>
+
+ * tree-vrp.c (extract_range_from_binary_expr): Don't shift by
+ floor_log2 of zero. Negate widened zero.
+
+2008-12-12 Ben Elliston <bje@au.ibm.com>
+
+ * config/fp-bit.c (nan): Rename from this ..
+ (makenan): .. to this.
+
+2008-12-11 Adam Nemet <anemet@caviumnetworks.com>
+
+ * config/mips/mips.md (*branch_bit<bbv><mode>,
+ *branch_bit<bbv><mode>_inverted): Renumber operands so that the
+ label becomes operands[1].
+
+2008-12-11 Harsha Jagasia <harsha.jagasia@amd.com>
+
+ 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 <grosser@fim.uni-passau.de>
+
+ * 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 <sebastian.pop@amd.com>
+
+ * 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 <grosser@fim.uni-passau.de>
+
+ 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 <dave.anglin@nrc-cnrc.gc.ca>
+
+ 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 <jakub@redhat.com>
+
+ 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 <sebastian.pop@amd.com>
+
+ 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 <sebastian.pop@amd.com>
+
+ * graphite.c (build_scops_1): Initialize open_scop.exit
+ and sinfo.last.
+
+2008-12-11 Sebastian Pop <sebastian.pop@amd.com>
+ Jan Sjodin <jan.sjodin@amd.com>
+ Harsha Jagasia <harsha.jagasia@amd.com>
+
+ 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 <rguenther@suse.de>
+
+ PR tree-optimization/36792
+ * tree-ssa-pre.c (compute_avail): Handle tcc_comparison like
+ tcc_binary.
+
+2008-12-10 Daniel Berlin <dberlin@dberlin.org>
+
+ PR tree-optimization/36792
+ * tree-ssa-pre.c (compute_avail): Don't insert defs into maximal set.
+
+2008-12-10 Alexandre Oliva <aoliva@redhat.com>
+
+ 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 <aoliva@redhat.com>
+
+ 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 <martinwguy@yahoo.it>
+
+ 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 <ebotcazou@adacore.com>
+
+ PR target/37170
+ PR target/38448
+ * final.c (output_addr_const) <SYMBOL_REF>: Call assemble_external
+ on the associated SYMBOL_REF_DECL node, if any.
+
+2008-12-09 David Daney <ddaney@caviumnetworks.com>
+
+ * config/mips/sync.md (sync_<optab>_12): Replace
+ MIPS_SYNC_OP_12_NOT_NOP with MIPS_SYNC_OP_12_AND.
+ (sync_old_<optab>_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_<optab>_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 <grosser@fim.uni-passau.de>
+
+ * 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 <grosser@fim.uni-passau.de>
+
+ * graphite.c (print_graphite_bb): Fix printing to file != dump_file.
+
+2008-12-09 Jakub Jelinek <jakub@redhat.com>
+
+ 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 <janis187@us.ibm.com>
+
+ * doc/sourcebuild.texi (Test Directives): Fix formatting.
+
+2008-12-09 Vladimir Makarov <vmakarov@redhat.com>
+
+ * 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 <bje@au.ibm.com>
+
+ * config/rs6000/linux-unwind.h (get_regs): Constify casts.
+
+2008-12-09 Jan Hubicka <jh@suse.cz>
+
+ * predict.c (estimate_bb_frequencies): Fix test if profile is present.
+
+2008-12-09 Jakub Jelinek <jakub@redhat.com>
+
+ 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 <rguenther@suse.de>
+
+ PR tree-optimization/38445
+ * tree-ssa-structalias.c (emit_pointer_definition): Only visit
+ names once.
+ (emit_alias_warning): Adjust.
+
+2008-12-09 Andrew Haley <aph@redhat.com>
+
+ * 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 <kai.tietz@onevision.com>
+
+ 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 <krebbel1@de.ibm.com>
+
+ * config/s390/s390.md (movti, movdi_64, movdi_31,
+ *movsi_zarch, *movhi, *movqi, *mov<mode>_64, *mov<mode>_31,
+ *mov<mode>_64dfp, *mov<mode>_64, *mov<mode>_31, mov<mode>): Remove
+ Q->Q alternative.
+ (Integer->BLKmode splitter): Removed.
+
+2008-12-08 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/alpha/alpha.c (alpha_set_memflags): Process memory
+ references in full insn sequence.
+
+2008-12-09 Jason Merrill <jason@redhat.com>
+
+ * 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 <grosser@fim.uni-passau.de>
+
+ 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 <bje@au.ibm.com>
+
+ * 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 <bje@au.ibm.com>
+
+ * config/rs6000/darwin-ldouble.c (fmsub): Remove unused variable, v.
+
+2008-12-08 Steve Ellcey <sje@cup.hp.com>
+
+ * config/ia64/ia64.md (UNSPECV_GOTO_RECEIVER): New constant.
+ (nonlocal_goto_receiver): New instruction.
+
+2008-12-08 Jakub Jelinek <jakub@redhat.com>
+
+ 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 <rth@redhat.com>
+
+ 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 <luisgpm@br.ibm.com>
+
+ * alias.c (find_base_term): Synch LO_SUM handling with what
+ find_base_value does.
+
+2008-12-08 Andrew Haley <aph@redhat.com>
+ Kamaraju Kusumanchi <raju.mailinglists@gmail.com>
+
+ * 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 <jakub@redhat.com>
+
+ 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 <ebotcazou@adacore.com>
+
+ * gimple.c (recalculate_side_effects) <tcc_constant>: New case.
+
+2008-12-07 Richard Guenther <rguenther@suse.de>
+
+ 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 <ebotcazou@adacore.com>
+
+ * 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 <steven@gcc.gnu.org>
PR rtl-optimization/36365
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
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) \
+2008-12-09 Jakub Jelinek <jakub@redhat.com>
+
+ 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 <sebastian.pop@amd.com>
PR bootstrap/38262
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);
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
= 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;
/* 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)
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;
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:
{
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);
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. */
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);
&& 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;
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)
{
{
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)
{
{
/* 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;
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);
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;
case FLOAT_EXPR:
case FIX_TRUNC_EXPR:
CASE_CONVERT:
+ case VIEW_CONVERT_EXPR:
pp_c_cast_expression (pp, e);
break;
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;
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);
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,
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;
/* 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);
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,
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
}
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),
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)
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
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-*-*)
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
&& !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 ();
}
\f
static rtx alpha_emit_set_const (rtx, enum machine_mode, HOST_WIDE_INT,
(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")])
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));
/* 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. */
INLINE
static fp_number_type *
-nan (void)
+makenan (void)
{
/* Discard the const qualifier... */
#ifdef TFLOAT
{
/* Adding infinities with opposite signs yields a NaN. */
if (isinf (b) && a->sign != b->sign)
- return nan ();
+ return makenan ();
return a;
}
if (isinf (b))
if (isinf (a))
{
if (iszero (b))
- return nan ();
+ return makenan ();
a->sign = a->sign != b->sign;
return a;
}
{
if (iszero (a))
{
- return nan ();
+ return makenan ();
}
b->sign = a->sign != b->sign;
return b;
if (isinf (a) || iszero (a))
{
if (a->class == b->class)
- return nan ();
+ return makenan ();
return a;
}
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),
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;
}
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)
--- /dev/null
+/* 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 <mmintrin.h>
+#endif
+
+#ifdef __SSE__
+#include <xmmintrin.h>
+#endif
+
+#ifdef __SSE2__
+#include <emmintrin.h>
+#endif
+
+#ifdef __SSE3__
+#include <pmmintrin.h>
+#endif
+
+#ifdef __SSSE3__
+#include <tmmintrin.h>
+#endif
+
+#ifdef __SSE4a__
+#include <ammintrin.h>
+#endif
+
+#if defined (__SSE4_2__) || defined (__SSE4_1__)
+#include <smmintrin.h>
+#endif
+
+#ifdef __SSE5__
+#include <bmmintrin.h>
+#endif
+
+#if defined (__AES__) || defined (__PCLMUL__)
+#include <wmmintrin.h>
+#endif
+
+/* For including AVX instructions */
+#include <immintrin.h>
+
+#ifdef __3dNOW__
+#include <mm3dnow.h>
+#endif
+
+#endif /* _X86INTRIN_H_INCLUDED */
(UNSPECV_PSAC_ALL 5) ; pred.safe_across_calls
(UNSPECV_PSAC_NORMAL 6)
(UNSPECV_SETJMP_RECEIVER 7)
+ (UNSPECV_GOTO_RECEIVER 8)
])
(include "predicates.md")
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)]
""
#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 */
{ 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 */\
PS_REGS,
SI_REGS,
HI_REGS,
+ R02A_REGS,
RA_REGS,
GENERAL_REGS,
FLG_REGS,
"PS_REGS", \
"SI_REGS", \
"HI_REGS", \
+"R02A_REGS", \
"RA_REGS", \
"GENERAL_REGS", \
"FLG_REGS", \
- 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:
- 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:
- 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:
/* 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
#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" \
/* 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.
#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" \
/* 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.
#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:
[(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>mode)"
{
return
mips_output_conditional_branch (insn, operands,
- MIPS_BRANCH ("bbit<bbv>", "%1,%2,%0"),
- MIPS_BRANCH ("bbit<bbinv>", "%1,%2,%0"));
+ MIPS_BRANCH ("bbit<bbv>", "%0,%2,%1"),
+ MIPS_BRANCH ("bbit<bbinv>", "%0,%2,%1"));
}
[(set_attr "type" "branch")
(set_attr "mode" "none")
[(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>mode)"
{
return
mips_output_conditional_branch (insn, operands,
- MIPS_BRANCH ("bbit<bbinv>", "%1,%2,%0"),
- MIPS_BRANCH ("bbit<bbv>", "%1,%2,%0"));
+ MIPS_BRANCH ("bbit<bbinv>", "%0,%2,%1"),
+ MIPS_BRANCH ("bbit<bbv>", "%0,%2,%1"));
}
[(set_attr "type" "branch")
(set_attr "mode" "none")
"GENERATE_LL_SC"
{
return (mips_output_sync_loop
- (MIPS_SYNC_OP_12 ("<insn>", MIPS_SYNC_OP_12_NOT_NOP)));
+ (MIPS_SYNC_OP_12 ("<insn>", MIPS_SYNC_OP_12_AND)));
}
[(set_attr "length" "40")])
"GENERATE_LL_SC"
{
return (mips_output_sync_loop
- (MIPS_SYNC_OLD_OP_12 ("<insn>", MIPS_SYNC_OLD_OP_12_NOT_NOP,
- MIPS_SYNC_OLD_OP_12_NOT_NOP_REG)));
+ (MIPS_SYNC_OLD_OP_12 ("<insn>", MIPS_SYNC_OLD_OP_12_AND)));
}
[(set_attr "length" "40")])
"GENERATE_LL_SC"
{
return (mips_output_sync_loop
- (MIPS_SYNC_NEW_OP_12 ("<insn>", MIPS_SYNC_NEW_OP_12_NOT_NOP)));
+ (MIPS_SYNC_NEW_OP_12 ("<insn>", MIPS_SYNC_NEW_OP_12_AND)));
}
[(set_attr "length" "40")])
"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<mode>"
[(parallel [
"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<mode>"
[(parallel [
"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")])
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);
/* 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];
} *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];
;
(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" "")
(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
#
#
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,
*,
*,
*,
- *,
*")
])
(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
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.
(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
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" "*,
*,
*,
*,
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,
*,
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
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,
z10_super_E1,
z10_super,
*,
- *,
*")
])
})
(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
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,
z10_super,
z10_rec,
z10_rec,
- z10_super,
- *")])
+ z10_super")])
(define_peephole2
[(set (match_operand:HI 0 "register_operand" "")
})
(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
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,
z10_super,
z10_rec,
z10_super,
- z10_super,
- *")])
+ z10_super")])
(define_peephole2
[(set (match_operand:QI 0 "nonimmediate_operand" "")
"")
(define_insn "*mov<mode>_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
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<mode>_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
(define_insn "*mov<mode>_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
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" "*,
*,
*,
*,
z10_fr_E1,
z10_fwd_A3,
- z10_rec,
- *")
+ z10_rec")
])
(define_insn "*mov<mode>_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
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<mode>,fload<mode>,fload<mode>,fload<mode>,
- fstore<mode>,fstore<mode>,lr,load,store,*")
+ fstore<mode>,fstore<mode>,lr,load,store")
(set_attr "z10prop" "*,
*,
*,
*,
z10_fr_E1,
z10_fwd_A3,
- z10_rec,
- *")])
+ z10_rec")])
(define_insn "*mov<mode>_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
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<mode>,fload<mode>,fload<mode>,fload<mode>,
- fstore<mode>,fstore<mode>,lm,lm,stm,stm,*,*,*")])
+ fstore<mode>,fstore<mode>,lm,lm,stm,stm,*,*")])
(define_split
[(set (match_operand:DD_DF 0 "nonimmediate_operand" "")
(define_insn "mov<mode>"
[(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
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<mode>,fload<mode>,fload<mode>,fload<mode>,
- fstore<mode>,fstore<mode>,lr,load,load,store,store,*")
+ fstore<mode>,fstore<mode>,lr,load,load,store,store")
(set_attr "z10prop" "*,
*,
*,
z10_fwd_A3,
z10_fwd_A3,
z10_super,
- z10_rec,
- *")])
+ z10_rec")])
;
; movcc instruction pattern
"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" "")
+2008-12-10 Jason Merrill <jason@redhat.com>
+
+ 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 <mark@codesourcery.com>
+
+ 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 <sje@cup.hp.com>
+
+ * decl2.c (mark_used): Remove assemble_external call.
+
+2008-12-08 Dodji Seketeli <dodji@redhat.com>
+
+ PR debug/38390
+ * name-lookup.c (kept_level_p): Don't forget the case of levels
+ having using directives.
+
+2008-12-08 Richard Henderson <rth@redhat.com>
+
+ 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 <jakub@redhat.com>
PR c++/35336
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);
/* 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,
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);
tf_warning_or_error);
arg = convert_for_arg_passing (type, arg);
}
+ pop_deferring_access_checks();
VEC_pop (tree, default_arg_context);
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;
}
}
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,
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))
/* 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;
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
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);
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);
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);
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)
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
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 ();
}
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. */
-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
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
@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
@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
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
#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. */
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
#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;
if ((enc & 0x70) != 0 && (enc & 0x70) != DW_EH_PE_pcrel)
return false;
+ saved_do_cfi_asm = true;
return true;
}
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;
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);
}
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
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. */
/* 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;
\f
+2008-12-12 Daniel Franke <franke.daniel@gmail.com>
+
+ 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 <rguenther@suse.de>
+
+ * Make-lang.in (install-finclude-dir): Use correct mode argument
+ for mkinstalldirs.
+
+2008-12-09 Daniel Franke <franke.daniel@gmail.com>
+
+ 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 <franke.daniel@gmail.com>
+
+ 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 <mikael.morin@tele2.fr>
+
+ PR fortran/37469
+ * expr.c (find_array_element): Simplify array bounds.
+ Assert that both bounds are constant expressions.
+
+2008-12-09 Mikael Morin <mikael.morin@tele2.fr>
+
+ 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 <jvdelisle@gcc.gnu.org>
PR fortran/38425
# 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
#\f
# Install hooks:
# f951 is installed elsewhere as part of $(COMPILERS).
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],
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],
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:
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;
}
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;
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);
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)
{
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]);
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
@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,
/* 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},
{".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},
{".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
Fortran
; Documented in C
+idirafter
+Fortran Joined Separate
+; Documented in C
+
imultilib
Fortran Joined Separate
; Documented in C
{
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
{
{
/* 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);
{
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;
OVERRIDE_ABI_FORMAT (fndecl);
#endif
+ invoke_set_current_function_hook (fndecl);
+
if (fndecl != NULL_TREE)
{
DECL_STRUCT_FUNCTION (fndecl) = cfun;
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
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. */
" 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
}
break;
+ case tcc_constant:
+ /* No side-effects. */
+ return;
+
default:
- /* Can never be used with non-expressions. */
gcc_unreachable ();
}
}
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, ...);
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;
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;
#include "tree-scalar-evolution.h"
#include "tree-pass.h"
#include "domwalk.h"
+#include "value-prof.h"
#include "pointer-set.h"
#include "gimple.h"
/* 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. */
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. */
VEC_free (iv_stack_entry_p, heap, *stack);
}
+\f
+
+/* 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);
+}
+
+\f
+
+/* 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. */
{
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;
}
}
-/* 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 *
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");
}
if (GBB_CONDITIONS (gb))
{
fprintf (file, " (conditions: \n");
- dump_gbb_conditions (dump_file, gb);
+ dump_gbb_conditions (file, gb);
fprintf (file, " )\n");
}
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
#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 *
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. */
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
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 ());
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);
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;
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;
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,
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. */
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
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.
if (p->t == var)
return i;
+ gcc_assert (SCOP_ADD_PARAMS (scop));
+
nvar = XNEW (struct name_tree);
nvar->t = var;
nvar->name = NULL;
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;
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);
}
}
/* 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
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. */
{
int i, j, row;
CloogMatrix *cstr;
+ graphite_bb_p gb;
int nb_rows = outer_cstr->NbRows + 1;
int nb_cols = outer_cstr->NbColumns + 1;
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);
}
/* 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);
}
/* 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))
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:
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. */
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)
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:
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
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
{
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)
{
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
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;
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. */
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;
}
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
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;
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. */
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)
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);
}
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);
}
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);
}
}
}
/* 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. */
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
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);
}
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);
}
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);
}
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);
}
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
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))
{
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. */
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.
/* 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);
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.
/* 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);
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);
}
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 ();
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);
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))
{
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. */
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
+#ifndef GCC_GRAPHITE_H
+#define GCC_GRAPHITE_H
+
#include "tree-data-ref.h"
typedef struct graphite_bb *graphite_bb_p;
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;
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:
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;
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
#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. */
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)
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. */
/* ??? 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
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
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. */
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. */
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. */
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 */
todo = optimize_inline_calls (current_function_decl);
timevar_pop (TV_INTEGRATION);
}
+ cfun->always_inline_functions_inlined = true;
return todo;
}
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];
}
/* 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)
{
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;
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;
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;
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++)
{
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);
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;
(&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;
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;
}
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)
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. */
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;
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,
}
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,
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);
}
}
}
/* 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. */
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
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);;
{
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))
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;
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)
/* 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];
/* 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);
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];
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]))
{
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. */
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)
}
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]);
}
}
-/* 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,
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));
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)
{
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))
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)
{
ira_allocno_t a;
ira_allocno_iterator ai;
+ HARD_REG_SET temp_hard_reg_set;
if (optimize)
{
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). */
}
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)
{
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)
/* 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;
{
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]);
}
}
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
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. */
> 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)
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
{
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
}
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))
{
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;
}
{
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);
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
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);
ira_emit (bool loops_p)
{
basic_block bb;
+ rtx insn;
edge_iterator ei;
edge e;
ira_allocno_t a;
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);
}
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
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
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;
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
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));
static void
mark_reg_live (rtx reg)
{
- int regno;
+ int i, regno;
gcc_assert (REG_P (reg));
regno = REGNO (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)
{
&& ! 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++;
}
}
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);
}
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)
{
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
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);
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;
+ }
+ }
}
}
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
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
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);
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]);
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 ();
}
\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 ())
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;
}
}
- /* 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);
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. */
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;
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;
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))
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;
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. */
/* 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);
}
}
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);
}
}
}
&& 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;
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;
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. */
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));
/* 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:
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:
/* 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;
case POINTER_TYPE:
case REFERENCE_TYPE:
{
-
enum machine_mode mode = ((TREE_CODE (type) == REFERENCE_TYPE
&& reference_types_internal)
? Pmode : TYPE_MODE (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)
/* 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
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;
+}
\f
/* Create and return a type for signed integers of PRECISION bits. */
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;
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;
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;
+2008-12-12 Daniel Franke <franke.daniel@gmail.com>
+
+ PR fortran/36355
+ * gfortran.dg/matmul_argument_types.f90: New.
+
+2008-12-11 Janis Johnson <janis187@us.ibm.com>
+
+ PR testsuite/29071
+ * gcc.dg/20020919-1.c: Fix a preprocessor check.
+
+2008-12-11 Sebastian Pop <sebastian.pop@amd.com>
+
+ PR middle-end/38413
+ * gcc.dg/graphite/pr38413.c: New.
+
+2008-12-11 Sebastian Pop <sebastian.pop@amd.com>
+
+ PR middle-end/37857
+ * gfortran.dg/graphite/pr37857.f90: New.
+
+2008-12-11 Harsha Jagasia <harsha.jagasia@amd.com>
+
+ PR tree-optimization/38446
+ * gcc.dg/graphite/pr38446.c: New.
+
+2008-12-11 Sebastian Pop <sebastian.pop@amd.com>
+
+ * 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 <grosser@fim.uni-passau.de>
+
+ PR middle-end/38459
+ * gfortran.dg/graphite/pr38459.f90: New.
+
+2008-12-11 Sebastian Pop <sebastian.pop@amd.com>
+
+ 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 <irar@il.ibm.com>
+
+ PR tree-optimization/38464
+ * gcc.dg/vect/costmodel/ppc/costmodel-slp-12.c: Check that three
+ loops are vectorized.
+
+2008-12-10 Jason Merrill <jason@redhat.com>
+
+ PR c++/35319
+ * g++.dg/ext/fixed2.C: New test.
+
+2008-12-10 Daniel Berlin <dberlin@dberlin.org>
+
+ PR tree-optimization/36792
+ * gcc.dg/tree-ssa/ssa-fre-10.c: Update expected results.
+
+2008-12-10 Alexandre Oliva <aoliva@redhat.com>
+
+ PR middle-end/38271
+ * gcc.dg/torture/pr38271.c: New.
+
+2008-12-10 Ira Rosen <irar@il.ibm.com>
+
+ PR tree-optimization/37416
+ * gcc.dg/vect/pr36630.c: Expect 1 vectorized loop.
+
+2008-12-10 Uros Bizjak <ubizjak@gmail.com>
+
+ * 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 <mark@codesourcery.com>
+
+ PR c++/37971
+ * g++.dg/overload/defarg2.C: New test.
+ * g++.dg/overload/defarg3.C: Likewise.
+
+2008-12-09 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/38454
+ * gcc.dg/memset-1.c: New test.
+ * gcc.dg/memcpy-2.c: New test.
+
+2008-12-09 Mikael Morin <mikael.morin@tele2.fr>
+
+ PR fortran/35983
+ * gfortran.dg/pr35983.f90: New test.
+
+2008-12-09 H.J. Lu <hongjiu.lu@intel.com>
+
+ 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 <sje@cup.hp.com>
+
+ PR testsuite/37326
+ * gcc.dg/tree-ssa/ssa-store-ccp-3.c: Skip on hppa*64-*-*.
+
+2008-12-09 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/35468
+ * gcc.dg/pr35468.c: New test.
+ * gcc.c-torture/compile/pr35468.c: New test.
+
+2008-12-08 Jason Merrill <jason@redhat.com>
+
+ PR c++/38410
+ * gcc.dg/ctor1.c: New test.
+
+2008-12-09 Tobias Grosser <grosser@fim.uni-passau.de>
+
+ PR middle-end/38084
+ * gfortran.dg/graphite/id-3.f90: New.
+ * gcc.dg/graphite/pr38084.c: New.
+
+2008-12-08 Uros Bizjak <ubizjak@gmail.com>
+
+ * 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 <dodji@redhat.com>
+
+ PR debug/38390
+ * g++.dg/debug/dwarf2/imported-module-2.C: New test.
+
+2008-12-08 Steve Ellcey <sje@cup.hp.com>
+
+ * g++.dg/other/packed1.C: Remove ia64-hp-hpux* XFAIL.
+
+2008-12-08 Steve Ellcey <sje@cup.hp.com>
+
+ * gcc.target/ia64/versionid-1.c (dg-final): Fix syntax.
+ * gcc.target/ia64/versionid-2.c (dg-final): Ditto.
+
+2008-12-08 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/35443
+ * gcc.dg/pr35443.c: New test.
+
+ PR c/35442
+ * gcc.dg/pr35442.c: New test.
+
+2008-12-07 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/string_comparison.adb: New test.
+
+2008-12-07 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR tree-optimization/38405
+ * gcc.dg/torture/pr38405.c: New.
+
+2008-12-07 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/aggr10.adb: New test.
+ * gnat.dg/aggr10_pkg.ads: New helper.
+
2008-12-06 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR fortran/38425
2008-09-24 Steve Ellcey <sje@cup.hp.com>
- * 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 <aldyh@redhat.com>
--- /dev/null
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// 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;
+}
+
--- /dev/null
+// PR c++/35319
+// { dg-options "" }
+
+void foo()
+{
+ throw 0r;
+}
-// { 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.
--- /dev/null
+// 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();
+}
--- /dev/null
+// 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" }
+};
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"
--- /dev/null
+/* PR tree-optimization/35468 */
+
+void
+foo (void)
+{
+ *(char *) "c" = 'x';
+}
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
|| 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
--- /dev/null
+/* 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 };
+}
#define MAX 8192
+void bar (void);
+
int main()
{
int i, j;
int A[MAX * MAX];
int B[MAX * MAX];
+ bar ();
+
for (i = 0; i < MAX; i++)
for (j = 0; j < MAX; j++)
{
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];
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" } } */
--- /dev/null
+/* { 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" } } */
--- /dev/null
+/* { 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" } } */
--- /dev/null
+/* { 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" } } */
--- /dev/null
+/* { 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" } } */
AssertH ( j < 256, 1005 );
}
/* { dg-final { scan-tree-dump-times "Loop blocked" 1 "graphite" { xfail *-*-* }} } */
+/* { dg-final { cleanup-tree-dump "graphite" } } */
}
prepare_new_block ( s );
}
+
+/* { dg-final { cleanup-tree-dump "graphite" } } */
--- /dev/null
+/* { dg-options "-O3 -floop-block" } */
+
+void test_sort()
+{
+ char *base;
+ register char c, *i, *hi;
+
+ for (i = base; i < hi; i++)
+ *i++ = c;
+}
+
--- /dev/null
+/* { 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; i<size; i++)
+ {
+ j = get_state(size,node, hash);
+ if(j == -1)
+ {
+ add_size++;
+ }
+ }
+
+ foo (size+add_size);
+}
--- /dev/null
+/* { dg-options "-O3 -fgraphite-identity" } */
+
+test_seg(int a, int b)
+{
+ int i,r=1;
+ for(i=0; i<b ;i++)
+ r*=a;
+ return r;
+}
--- /dev/null
+/* { dg-options "-O3 -fgraphite-identity" } */
+
+typedef struct {
+ unsigned int avail_out;
+ void *state;
+} stream;
+
+typedef struct {
+ stream* test;
+ int num;
+} state_in;
+
+int test_in ( stream *test, int action )
+{
+ state_in* tst;
+ if (test == ((void *)0)) return (-2);
+ if (tst == ((void *)0)) return (-2);
+ if (tst->test != 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;
+}
--- /dev/null
+/* { 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;
+}
--- /dev/null
+/* { 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;
+ }
+}
--- /dev/null
+/* { 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];
+}
+
&& --chain_length != 0);
return best_len;
}
+
/* { dg-final { scan-tree-dump-times "number of SCoPs: 0" 1 "graphite"} } */
/* { dg-final { cleanup-tree-dump "graphite" } } */
-/* { 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 ()
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" } } */
-/* { 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 ()
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" } } */
-/* { dg-options "-O2 -floop-block -fdump-tree-graphite-all" } */
+/* { dg-options "-O2 -fgraphite -fdump-tree-graphite-all" } */
#define N 24
#define M 1000
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" } } */
--- /dev/null
+/* 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" } } */
--- /dev/null
+/* { 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;
+}
/* 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__)
--- /dev/null
+/* 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" } */
+}
--- /dev/null
+/* PR c/35443 */
+/* { dg-options "" } */
+/* { dg-bogus "not supported by" "" { target *-*-* } 0 } */
+
+void
+foo ()
+{
+ ({ int i; i; })(); /* { dg-error "is not a function" } */
+}
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* { 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);
+}
--- /dev/null
+/* { 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;
+}
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"
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 (;;) {
}
}
-/* { dg-final { scan-tree-dump-not "Insertions:" "pre" } } */
+/* { dg-final { scan-tree-dump "Insertions: 2" "pre" } } */
/* { dg-final { cleanup-tree-dump "pre" } } */
/* { dg-do compile } */
-/* { dg-skip-if "" { *-*-darwin* } { "*" } { "" } } */
+/* { dg-skip-if "" { *-*-darwin* hppa*64*-*-* } { "*" } { "" } } */
/* { dg-options "-O2 -fno-common -fdump-tree-optimized" } */
const int conststaticvariable;
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" } } */
i = i + 1;
}
}
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
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" } } */
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" } } */
--- /dev/null
+/* { 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; }
return (foo() + 1);
}
-/* { dg-final { scan-assembler "alias.*foo.*foo{20040821}" } } */
+/* { dg-final { scan-assembler "alias.*foo.*foo\\\{20040821\\\}" } } */
return (1);
}
-/* { dg-final { scan-assembler "alias.*foo.*foo{20040821}" } } */
+/* { dg-final { scan-assembler "alias.*foo.*foo\\\{20040821\\\}" } } */
/* { 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);
__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();
/* { 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)
{
/* { 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)
{
! { dg-do run }
+! { dg-options "-mieee" { target alpha*-*-* } }
! PR fortran/36214
! For BOZ-initialization of floats, the precision used to be wrong sometimes.
! { dg-do run }
! { dg-options "-fno-range-check" }
+! { dg-options "-fno-range-check -mieee" { target alpha*-*-* } }
!
! PR fortran/34342
!
-! { 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.
!
--- /dev/null
+! { 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
--- /dev/null
+! { 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
--- /dev/null
+! { 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
--- /dev/null
+! { 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
--- /dev/null
+! { 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
--- /dev/null
+! { 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
--- /dev/null
+! { 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
--- /dev/null
+! { dg-options "-O2 -fgraphite-identity" }
+# 1 "mltfftsg.F"
+# 1 "<built-in>"
+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
! { 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
! { dg-do run }
! { dg-options "-finit-real=inf" }
+! { dg-options "-finit-real=inf -mieee" { target alpha*-*-* } } */
program init_flag_4
call real_test
! { dg-do run }
! { dg-options "-finit-real=-inf" }
+! { dg-options "-finit-real=-inf -mieee" { target alpha*-*-* } } */
program init_flag_5
call real_test
! { 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
! { dg-do run }
! { dg-options "-fno-range-check" }
+! { dg-options "-fno-range-check -mieee" { target alpha*-*-* } } */
module mod_check
implicit none
! 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
!
! { 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
--- /dev/null
+! { 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
! { 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
!
! { dg-do run { target fd_truncate } }
-! { dg-options "-mieee" { target sh*-*-* } }
+! { dg-options "-mieee" { target alpha*-*-* sh*-*-* } }
!
! PR fortran/34427
!
! { dg-do run { target fd_truncate } }
-! { dg-options "-mieee" { target sh*-*-* } }
+! { dg-options "-mieee" { target alpha*-*-* sh*-*-* } }
!
! PR fortran/34427
!
! as arguments
!
! { dg-do run }
-! { dg-options "-pedantic-errors -mieee" { target sh*-*-* } }
+! { dg-options "-pedantic-errors -mieee" { target alpha*-*-* sh*-*-* } }
!
module aux2
interface isnan
! { 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
!
! { 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
!
! { 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.
!
! { 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
! { 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
!
! { dg-do run }
-! { dg-options "-pedantic-errors -mieee" { target sh*-*-* } }
+! { dg-options "-pedantic-errors -mieee" { target alpha*-*-* sh*-*-* } }
!
! PR fortran/34209
!
--- /dev/null
+! { 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
! 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)
!{ 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 <jvdelisle@gcc.gnu.org>
program main
! { 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
--- /dev/null
+add-ieee-options
+return 0
--- /dev/null
+-- { 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;
--- /dev/null
+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;
--- /dev/null
+-- { 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;
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. */
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)
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);
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);
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)
/* 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));
}
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)
{
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
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"
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;
}
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
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
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
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,
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;
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. */
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);
}
if (is_exception_related (stmt))
continue;
case tcc_binary:
+ case tcc_comparison:
{
vn_nary_op_t nary;
unsigned int i;
/* 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;
{
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);
}
static void
emit_alias_warning (tree ptr)
{
- gimple def = SSA_NAME_DEF_STMT (ptr);
gimple use;
imm_use_iterator ui;
unsigned warned = 0;
}
}
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
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;
!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:
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;
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;
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);
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);
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);
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);
#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)
#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
2008-12-10 Jason Merrill <jason@redhat.com>
- * demangle.h (enum demangle_component_type): Add
+ * demangle.h (enum demangle_component_type): Add
DEMANGLE_COMPONENT_FIXED_TYPE.
-2008-12-01 Cary Coutant <ccoutant@google.com>
-
- * plugin-api.h (ld_plugin_message): Change format parameter to const.
-
-2008-12-01 Cary Coutant <ccoutant@google.com>
-
- * plugin-api.h: Fix syntax error when compiling with C++.
-
-2008-11-26 Alan Modra <amodra@bigpond.net.au>
-
- PR 7047
- * bfdlink.h (struct bfd_elf_version_expr): Delete "symbol".
- Add "literal".
-
-2008-11-21 Sterling Augustine <sterling@tensilica.com>
-
- * 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 <bob.wilson@acm.org>
* xtensa-config.h (XCHAL_HAVE_MUL16, XCHAL_HAVE_MUL32, XCHAL_HAVE_DIV32)
+2008-12-10 Alexandre Oliva <aoliva@redhat.com>
+
+ 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 <joseph@codesourcery.com>
* lex.c (cpp_token_len): Use 6 as default length.
/* 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
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;
+2008-12-08 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+
+ 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 <jvdelisle@gcc.gnu.org>
PR libfortran/38291
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
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");
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;
+ } */
}
+2008-12-08 Jakub Jelinek <jakub@redhat.com>
+
+ 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 <janis187@us.ibm.com>
PR libgomp/38270
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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;
+}
+2008-12-11 H.J. Lu <hongjiu.lu@intel.com>
+
+ 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 <howarth@bromo.med.uc.edu>
- * 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 <howarth@bromo.med.uc.edu>
+2008-12-11 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/37582
+ * testsuite/26_numerics/headers/cmath/37582.cc: New.
+
+2008-12-08 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * 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 <paolo.carlini@oracle.com>
PR libstdc++/38421
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);
--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
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);
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
_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
const forward_list<_Tp, _Alloc>& __ly)
{ return !(__ly < __lx); }
- /// See std::forward_list::forward_swap().
+ /// See std::forward_list::swap().
template<typename _Tp, typename _Alloc>
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<typename _Tp, typename _Alloc>
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<typename _Tp, typename _Alloc>
inline void
swap(forward_list<_Tp, _Alloc>& __lx,
#undef remainderf
#undef remainderl
#undef remquo
-#undef remquo
-#undef remquo
+#undef remquof
+#undef remquol
#undef rint
#undef rintf
#undef rintl
using ::remainderl;
using ::remquo;
- using ::remquo;
- using ::remquo;
+ using ::remquof;
+ using ::remquol;
using ::rint;
using ::rintf;
--- /dev/null
+// 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 <cmath>
+
+struct foo
+{
+ foo (double);
+};
+
+bool operator &&(int, const foo &);
+
+// libstdc++/37582
+double
+test01(double x)
+{
+ return std::pow (x, 2.0);
+}
// 2006-02-07 Paolo Carlini <pcarlini@suse.de>
//
-// 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
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);