diff options
80 files changed, 5252 insertions, 1389 deletions
diff --git a/ChangeLog b/ChangeLog index f04ae63c501..e5223ad0e96 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2008-09-20 Steven Bosscher <steven@gcc.gnu.org> + + * MAINTAINERS: Add myself in "Write After Approval". + 2008-09-18 Steve Ellcey <sje@cup.hp.com> * MAINTAINERS: Add myself as ia64 maintainer. diff --git a/ChangeLog.melt b/ChangeLog.melt index fe654381e3b..c3838e8ab61 100644 --- a/ChangeLog.melt +++ b/ChangeLog.melt @@ -1,3 +1,6 @@ +2008-09-22 Basile Starynkevitch <basile@starynkevitch.net> + MELT branch merged with trunk r140542 + 2008-09-18 Basile Starynkevitch <basile@starynkevitch.net> MELT branch merged with trunk r140490 diff --git a/MAINTAINERS b/MAINTAINERS index 111f17cc6c6..6c8314021d4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -280,6 +280,7 @@ Segher Boessenkool segher@kernel.crashing.org Andrea Bona andrea.bona@st.com Paolo Bonzini bonzini@gnu.org Neil Booth neil@daikokuya.co.uk +Steven Bosscher steven@gcc.gnu.org Robert Bowdidge bowdidge@apple.com Joel Brobecker brobecker@gnat.com Dave Brolley brolley@redhat.com diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ac957740e4c..9f67a4c0e91 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,148 @@ +2008-09-21 Jan Hubicka <jh@suse.cz> + + * ipa-cp.c (ipcp_estimate_growth): Check recursive calls. + (ipcp_insert_stage): Update dead_nodes bitmap. + +2008-09-22 Danny Smith <dannysmith@users.sourceforge.net> + + PR target/37528 + * config/i386/t-cygming (SHLIB_LC): Remove. + (SHLIB_LINK): Don't add static objects to SHLIB_IMPLIB + * config/i386/t-cygwin (SHLIB_LC): Specify all required + libraries. + +2008-09-22 Hans-Peter Nilsson <hp@axis.com> + + PR middle-end/37170 + PR middle-end/37280 + * final.c (mark_symbol_ref_as_used): New helper function. + (output_operand): Instead of just looking inside MEMs for + SYMBOL_REFs, use new helper function and for_each_rtx. + * varasm.c (assemble_external): Move #ifndef ASM_OUTPUT_EXTERNAL + to after weak-handling. Don't mark decls with TREE_STATIC as weak. + Make head comment more general. + * config/darwin.c (machopic_output_indirection): Handle weak + references here, like in assemble_external. + +2008-09-21 Eric Botcazou <ebotcazou@adacore.com> + + * config/sparc/sparc-protos.h (gen_compare_operator): Declare. + (sparc_emit_float_lib_cmp): Change return type. + * config/sparc/sparc.c (gen_compare_reg): Add comment about TFmode. + (gen_compare_operator): New function. + (sparc_emit_float_lib_cmp): Return the new operator to be used in + the comparison sequence. Minor tweaks. + * config/sparc/sparc.md (seq, sne, sgt, slt, sge, sle): Assert + that the final operator and the result of sparc_emit_float_lib_cmp + match for software TFmode; use emit_insn in lieu of emit_jump_insn. + (beq, bne, bgt, blt, bge, ble, bunordered, bordered, bungt, bunlt, + buneq, bunge, bunle, bltgt): Assert that the final operator and the + result of sparc_emit_float_lib_cmp match for software TFmode. + (movqicc, movhicc, movsicc, movdicc): Merge into... + (mov<I:mode>cc): ...this. + (movsfcc, movdfcc, movtfcc): Merge into... + (mov<F:mode>cc): ...this. + (movqi_cc_sp64, movhi_cc_sp64, movsi_cc_sp64, movdi_cc_sp64): Merge + into... + (mov<I:mode>_cc_v9): ...this. + (movdi_cc_sp64_trunc): Delete. + (movqi_cc_reg_sp64, movhi_cc_reg_sp64, movsi_cc_reg_sp64, + movdi_cc_reg_sp64): Merge into... + (mov<I:mode>_cc_reg_sp64): ...this. + (movsf_cc_sp64): Rename into... + (movsf_cc_v9): ...this. + (movdf_cc_sp64): Rename into... + (movdf_cc_v9): ...this. + (movtf_cc_hq_sp64): Rename into... + (movtf_cc_hq_v9): ...this. + (movtf_cc_sp64): Rename into... + (movtf_cc_v9): ...this. Adjust for renaming of movdf_cc_sp64. + +2008-09-21 Diego Novillo <dnovillo@google.com> + + * doc/gccint.texi: Include generic.texi and gimple.texi. + Re-order index. + * doc/tree-ssa.texi (GENERIC): Move to generic.texi. + (GIMPLE): Move to gimple.texi. + (Annotations): Remove references to to stmt_ann_t and + ssa_name_ann_t. + (SSA Operands): Rename from 'Statement Operands'. + * doc/generic.texi: New. + * doc/gimple.texi: New. + * Makefile.in (TEXI_GCCINT_FILES): Add generic.texi and + gimple.texi. + * Makefile.in (TEXI_GCCINT_FILES): + * gimple.c (gimple_copy_call_skip_args): Rename from + giple_copy_call_skip_args. Update all users. + * doc/gimple.texi (gimple_copy_call_skip_args): Document. + +2008-09-21 Ira Rosen <irar@il.ibm.com> + + PR tree-optimization/37539 + * tree-vect-transform.c (vect_transform_strided_load): Save vector + statement in related statement field only for the first load of the + group of loads with the same data reference. + +2008-09-20 Adam Nemet <anemet@caviumnetworks.com> + + * config/mips/mips.h (TUNE_OCTEON): New macro. + * config/mips/mips.c (mips_issue_rate): Return 2 for Octeon. + (mips_multipass_dfa_lookahead): Return 2 for Octeon. + * config/mips/octeon.md: New file. + * config/mips/mips.md: Include octeon.md. Restore + semi-alphabetical order of include files. + +2008-09-20 H.J. Lu <hongjiu.lu@intel.com> + + PR target/37571 + * config/i386/i386.md (*jcc_fused_1): Removed. + (*jcc_fused_2): Likewise. + (*jcc_fused_3): Likewise. + (*jcc_fused_4): Likewise. + +2008-09-20 Richard Sandiford <rdsandiford@googlemail.com> + + * doc/tm.texi (TARGET_IRA_COVER_CLASSES): Define. + (IRA_COVER_CLASSES): Refer to TARGET_IRA_COVER_CLASSES. + * target.h (gcc_target): Add ira_cover_classes. + * ira.c: Remove IRA_COVER_CLASSES guards. + (setup_cover_and_important_classes): Use targetm.ira_cover_classes + instead of IRA_COVER_CLASSES. + (setup_cover_and_important_classes): Remove IRA_COVER_CLASSES guard. + (setup_class_translate): Likewise. + (setup_reg_class_intersect_union): Likewise. + (find_reg_class_closure): Replace IRA_COVER_CLASSES guard with a + test of targetm.ira_cover_classes. + * opts.c (decode_options): Use targetm.ira_cover_classes instead + of IRA_COVER_CLASSES. + * target-def.h (TARGET_IRA_COVER_CLASSES): Define. + (TARGET_INITIALIZER): Include it. + * targhooks.h (default_ira_cover_classes): Declare. + * targhooks.c (default_ira_cover_classes): New function. + +2008-09-19 Bob Wilson <bob.wilson@acm.org> + + * config/xtensa/xtensa.md (reload<mode>_literal): Handle MEM operands. + +2008-09-19 Ian Lance Taylor <iant@google.com> + + * varasm.c (narrowing_initializer_constant_valid_p): Return + NULL_TREE if ENDTYPE is not an integer. + +2008-09-19 Andrew Pinski <andrew_pinski@playstation.sony.com> + + PR tree-opt/30930 + * tree-ssa.c (execute_update_addresses_taken): Also update + DECL_GIMPLE_REG_P for vector and complex types. + +2008-09-19 Andrew MacLeod <amacleod@redhat.com> + Jan Hubicka <jh@suse.cz> + + PR middle-end/37567 + * tree-ssa-ter.c (free_temp_expr_table): Make sure fields are actually + empty before freeing them. + (find_replaceable_exprs): Move asserts to free_temp_expr_table. + 2008-09-18 Bob Wilson <bob.wilson@acm.org> * configure.ac: Add HAVE_AS_TLS check for Xtensa. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 7b605fab072..0257b41a77b 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20080919 +20080922 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 42486eca87b..6befd2f08f9 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -3913,7 +3913,8 @@ TEXI_GCCINT_FILES = gccint.texi gcc-common.texi gcc-vers.texi \ configfiles.texi collect2.texi headerdirs.texi funding.texi \ gnu.texi gpl_v3.texi fdl.texi contrib.texi languages.texi \ sourcebuild.texi gty.texi libgcc.texi cfg.texi tree-ssa.texi \ - loop.texi melt.texi + loop.texi generic.texi gimple.texi melt.texi + TEXI_GCCINSTALL_FILES = install.texi install-old.texi fdl.texi \ gcc-common.texi gcc-vers.texi diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 5d6ecc80329..fe89a54c22f 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,30 @@ +2008-09-21 Laurent Guerby <laurent@guerby.net> + + PR ada/5911 + * gcc-interface/Makefile.in: Add multilib handling for x86_64 + and sparc. + * system-linux-sparcv9.ads: New file. + +2008-09-20 Eric Botcazou <ebotcazou@adacore.com> + + * exp_dbug.ads: Document new convention for the XVZ variable. + * gcc-interface/decl.c (gnat_to_gnu_entity) <E_Array_Type>: Generate + debug info if necessary for the type padding the component type. + <E_Array_Subtype>: Likewise. + (maybe_pad_type): Emit the XVZ variable in units. + * gcc-interface/trans.c (Loop_Statement_to_gnu): Fix formatting nits. + (Subprogram_Body_to_gnu): Set the source line of the subprogram's node + on statements generated to initialize the parameter attributes cache. + Set the source line of the end label of the body on the special return + statement built for a procedure with copy-in copy-out parameters. + +2008-09-20 Eric Botcazou <ebotcazou@adacore.com> + + PR ada/37585 + * gcc-interface/utils.c (create_subprog_decl): Disable inlining for + inlined external functions if they contain a nested function not + declared inline. + 2008-09-18 Jan Hubicka <jh@suse.cz> * gcc-interface/utils.c (create_subprog_decl): Use DECL_DECLARED_INLINE_P. diff --git a/gcc/ada/exp_dbug.ads b/gcc/ada/exp_dbug.ads index 71c2f79b14f..3a6297ce9ee 100644 --- a/gcc/ada/exp_dbug.ads +++ b/gcc/ada/exp_dbug.ads @@ -851,7 +851,7 @@ package Exp_Dbug is -- The size of the objects typed as x should be obtained from the -- structure of x (and x___XVE, if applicable) as for ordinary types -- unless there is a variable named x___XVZ, which, if present, will - -- hold the size (in bits) of x. + -- hold the size (in bytes) of x. -- The type x will either be a subtype of y (see also Subtypes of -- Variant Records, below) or will contain no fields at all. The layout, diff --git a/gcc/ada/gcc-interface/Makefile.in b/gcc/ada/gcc-interface/Makefile.in index ccd20bd1733..59803ca1ed2 100644 --- a/gcc/ada/gcc-interface/Makefile.in +++ b/gcc/ada/gcc-interface/Makefile.in @@ -316,6 +316,18 @@ else osys:=$(word 3,$(targ)) endif +# Make arch match the current multilib so that the RTS selection code +# picks up the right files. For a given target this must be coherent +# with MULTILIB_DIRNAMES defined in gcc/config/target/t-*. + +ifeq ($(strip $(filter-out %x86_64, $(arch))),) + ifeq ($(strip $(MULTISUBDIR)),/32) + arch:=i686 + endif +endif + +# ???: handle more multilib targets + # LIBGNAT_TARGET_PAIRS is a list of pairs of filenames. # The members of each pair must be separated by a '<' and no whitespace. # Each pair must be separated by some amount of whitespace from the following @@ -1467,7 +1479,7 @@ ifeq ($(strip $(filter-out powerpc% linux%,$(arch) $(osys))),) endif ifeq ($(strip $(filter-out sparc% linux%,$(arch) $(osys))),) - LIBGNAT_TARGET_PAIRS = \ + LIBGNAT_TARGET_PAIRS_32 = \ a-intnam.ads<a-intnam-linux.ads \ s-inmaop.adb<s-inmaop-posix.adb \ s-intman.adb<s-intman-posix.adb \ @@ -1482,6 +1494,27 @@ ifeq ($(strip $(filter-out sparc% linux%,$(arch) $(osys))),) s-tpopsp.adb<s-tpopsp-posix-foreign.adb \ system.ads<system-linux-sparc.ads + LIBGNAT_TARGET_PAIRS_64 = \ + a-intnam.ads<a-intnam-linux.ads \ + s-inmaop.adb<s-inmaop-posix.adb \ + s-intman.adb<s-intman-posix.adb \ + s-linux.ads<s-linux.ads \ + s-osinte.adb<s-osinte-posix.adb \ + s-osinte.ads<s-osinte-linux.ads \ + s-osprim.adb<s-osprim-posix.adb \ + s-taprop.adb<s-taprop-linux.adb \ + s-tasinf.ads<s-tasinf-linux.ads \ + s-tasinf.adb<s-tasinf-linux.adb \ + s-taspri.ads<s-taspri-posix-noaltstack.ads \ + s-tpopsp.adb<s-tpopsp-posix-foreign.adb \ + system.ads<system-linux-sparcv9.ads + + ifeq ($(strip $(MULTISUBDIR)),/64) + LIBGNAT_TARGET_PAIRS = $(LIBGNAT_TARGET_PAIRS_64) + else + LIBGNAT_TARGET_PAIRS = $(LIBGNAT_TARGET_PAIRS_32) + endif + TOOLS_TARGET_PAIRS = \ mlib-tgt-specific.adb<mlib-tgt-specific-linux.adb \ indepsw.adb<indepsw-gnu.adb diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c index c254990d45c..a8fa1badac3 100644 --- a/gcc/ada/gcc-interface/decl.c +++ b/gcc/ada/gcc-interface/decl.c @@ -1955,8 +1955,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) never be declared otherwise. This is necessary to ensure that its subtrees are properly marked. */ if (tem != orig_tem) - create_type_decl (TYPE_NAME (tem), tem, NULL, true, false, - gnat_entity); + create_type_decl (TYPE_NAME (tem), tem, NULL, true, + debug_info_p, gnat_entity); } if (Has_Volatile_Components (gnat_entity)) @@ -2324,7 +2324,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) to ensure that its subtrees are properly marked. */ if (gnu_type != orig_gnu_type) create_type_decl (TYPE_NAME (gnu_type), gnu_type, NULL, - true, false, gnat_entity); + true, debug_info_p, gnat_entity); } if (Has_Volatile_Components (Base_Type (gnat_entity))) @@ -5867,8 +5867,8 @@ maybe_pad_type (tree type, tree size, unsigned int align, if (size && TREE_CODE (size) != INTEGER_CST && definition) create_var_decl (concat_id_with_name (name, "XVZ"), NULL_TREE, - bitsizetype, TYPE_SIZE (record), false, false, false, - false, NULL, gnat_entity); + sizetype, TYPE_SIZE_UNIT (record), false, false, + false, false, NULL, gnat_entity); } rest_of_record_type_compilation (record); diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c index 938408bf8e1..9a6f4cf36ef 100644 --- a/gcc/ada/gcc-interface/trans.c +++ b/gcc/ada/gcc-interface/trans.c @@ -1689,17 +1689,20 @@ Loop_Statement_to_gnu (Node_Id gnat_node) push_stack (&gnu_loop_label_stack, NULL_TREE, LOOP_STMT_LABEL (gnu_loop_stmt)); - /* Set the condition that under which the loop should continue. - For "LOOP .... END LOOP;" the condition is always true. */ + /* Set the condition under which the loop must keep going. + For the case "LOOP .... END LOOP;" the condition is always true. */ if (No (gnat_iter_scheme)) ; - /* The case "WHILE condition LOOP ..... END LOOP;" */ + + /* For the case "WHILE condition LOOP ..... END LOOP;" it's immediate. */ else if (Present (Condition (gnat_iter_scheme))) LOOP_STMT_TOP_COND (gnu_loop_stmt) = gnat_to_gnu (Condition (gnat_iter_scheme)); + + /* Otherwise we have an iteration scheme and the condition is given by + the bounds of the subtype of the iteration variable. */ else { - /* We have an iteration scheme. */ Node_Id gnat_loop_spec = Loop_Parameter_Specification (gnat_iter_scheme); Entity_Id gnat_loop_var = Defining_Entity (gnat_loop_spec); Entity_Id gnat_type = Etype (gnat_loop_var); @@ -1745,7 +1748,7 @@ Loop_Statement_to_gnu (Node_Id gnat_node) gnu_loop_var = convert (get_base_type (gnu_type), gnu_loop_var); /* Set either the top or bottom exit condition as appropriate depending - on whether or not we know an overflow cannot occur. */ + on whether or not we know an overflow cannot occur. */ if (gnu_cond_expr) LOOP_STMT_BOT_COND (gnu_loop_stmt) = build_binary_op (NE_EXPR, integer_type_node, @@ -1763,12 +1766,12 @@ Loop_Statement_to_gnu (Node_Id gnat_node) convert (TREE_TYPE (gnu_loop_var), integer_one_node)); set_expr_location_from_node (LOOP_STMT_UPDATE (gnu_loop_stmt), - gnat_iter_scheme); + gnat_iter_scheme); } /* If the loop was named, have the name point to this loop. In this case, the association is not a ..._DECL node, but the end label from this - LOOP_STMT. */ + LOOP_STMT. */ if (Present (Identifier (gnat_node))) save_gnu_tree (Entity (Identifier (gnat_node)), LOOP_STMT_LABEL (gnu_loop_stmt), true); @@ -1788,7 +1791,7 @@ Loop_Statement_to_gnu (Node_Id gnat_node) } /* If we have an outer COND_EXPR, that's our result and this loop is its - "true" statement. Otherwise, the result is the LOOP_STMT. */ + "true" statement. Otherwise, the result is the LOOP_STMT. */ if (gnu_cond_expr) { COND_EXPR_THEN (gnu_cond_expr) = gnu_loop_stmt; @@ -1981,11 +1984,11 @@ Subprogram_Body_to_gnu (Node_Id gnat_node) for (i = 0; VEC_iterate (parm_attr, cache, i, pa); i++) { if (pa->first) - add_stmt (pa->first); + add_stmt_with_node (pa->first, gnat_node); if (pa->last) - add_stmt (pa->last); + add_stmt_with_node (pa->last, gnat_node); if (pa->length) - add_stmt (pa->length); + add_stmt_with_node (pa->length, gnat_node); } add_stmt (gnu_result); @@ -2017,7 +2020,7 @@ Subprogram_Body_to_gnu (Node_Id gnat_node) add_stmt_with_node (build_return_expr (DECL_RESULT (gnu_subprog_decl), gnu_retval), - gnat_node); + End_Label (Handled_Statement_Sequence (gnat_node))); gnat_poplevel (); gnu_result = end_stmt_group (); } diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c index 608f6ecd865..7f1bc7bebbb 100644 --- a/gcc/ada/gcc-interface/utils.c +++ b/gcc/ada/gcc-interface/utils.c @@ -1973,12 +1973,16 @@ create_subprog_decl (tree subprog_name, tree asm_name, tree return_type = TREE_TYPE (subprog_type); tree subprog_decl = build_decl (FUNCTION_DECL, subprog_name, subprog_type); - /* If this is a function nested inside an inlined external function, it - means we aren't going to compile the outer function unless it is - actually inlined, so do the same for us. */ - if (current_function_decl && DECL_DECLARED_INLINE_P (current_function_decl) + /* If this is a non-inline function nested inside an inlined external + function, we cannot honor both requests without cloning the nested + function in the current unit since it is private to the other unit. + We could inline the nested function as well but it's probably better + to err on the side of too little inlining. */ + if (!inline_flag + && current_function_decl + && DECL_DECLARED_INLINE_P (current_function_decl) && DECL_EXTERNAL (current_function_decl)) - extern_flag = true; + DECL_DECLARED_INLINE_P (current_function_decl) = 0; DECL_EXTERNAL (subprog_decl) = extern_flag; TREE_PUBLIC (subprog_decl) = public_flag; @@ -1986,6 +1990,7 @@ create_subprog_decl (tree subprog_name, tree asm_name, TREE_READONLY (subprog_decl) = TYPE_READONLY (subprog_type); TREE_THIS_VOLATILE (subprog_decl) = TYPE_VOLATILE (subprog_type); TREE_SIDE_EFFECTS (subprog_decl) = TYPE_VOLATILE (subprog_type); + DECL_DECLARED_INLINE_P (subprog_decl) = inline_flag; DECL_ARGUMENTS (subprog_decl) = param_decl_list; DECL_RESULT (subprog_decl) = build_decl (RESULT_DECL, 0, return_type); DECL_ARTIFICIAL (DECL_RESULT (subprog_decl)) = 1; @@ -2004,9 +2009,6 @@ create_subprog_decl (tree subprog_name, tree asm_name, DECL_BY_REFERENCE (result_decl) = 1; } - if (inline_flag) - DECL_DECLARED_INLINE_P (subprog_decl) = 1; - if (asm_name) { SET_DECL_ASSEMBLER_NAME (subprog_decl, asm_name); diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c index 20cce264101..fe332738c54 100644 --- a/gcc/config/darwin.c +++ b/gcc/config/darwin.c @@ -1002,6 +1002,30 @@ machopic_output_indirection (void **slot, void *data) rtx init = const0_rtx; switch_to_section (darwin_sections[machopic_nl_symbol_ptr_section]); + + /* Mach-O symbols are passed around in code through indirect + references and the original symbol_ref hasn't passed through + the generic handling and reference-catching in + output_operand, so we need to manually mark weak references + as such. */ + if (SYMBOL_REF_WEAK (symbol)) + { + tree decl = SYMBOL_REF_DECL (symbol); + gcc_assert (DECL_P (decl)); + + if (decl != NULL_TREE + && DECL_EXTERNAL (decl) && TREE_PUBLIC (decl) + /* Handle only actual external-only definitions, not + e.g. extern inline code or variables for which + storage has been allocated. */ + && !TREE_STATIC (decl)) + { + fputs ("\t.weak_reference ", asm_out_file); + assemble_name (asm_out_file, sym_name); + fputc ('\n', asm_out_file); + } + } + assemble_name (asm_out_file, ptr_name); fprintf (asm_out_file, ":\n"); diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 66d186686f7..de58df39edc 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -14267,76 +14267,6 @@ (const_int 2) (const_int 6)))]) -;; ??? Handle alignment requirements for compare and branch fused macro-op; -;; the branch instruction does not start at a 16-byte boundary or cross -;; a 16-byte boundary. - -(define_insn "*jcc_fused_1" - [(set (pc) - (if_then_else (match_operator 1 "comparison_operator" - [(match_operand:SWI32 2 "register_operand" "<r>") - (match_operand:SWI32 3 "const0_operand" "")]) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_FUSE_CMP_AND_BRANCH && !TARGET_64BIT" -{ - return "test{<imodesuffix>}\t%2, %2\n\t" - "%+j%E1\t%l0\t" ASM_COMMENT_START " fused"; -} - [(set_attr "type" "multi") - (set_attr "mode" "<MODE>")]) - -(define_insn "*jcc_fused_2" - [(set (pc) - (if_then_else (match_operator 1 "comparison_operator" - [(match_operand:SWI32 2 "register_operand" "<r>") - (match_operand:SWI32 3 "const0_operand" "")]) - (pc) - (label_ref (match_operand 0 "" ""))))] - "TARGET_FUSE_CMP_AND_BRANCH && !TARGET_64BIT" -{ - return "test{<imodesuffix>}\t%2, %2\n\t" - "%+j%e1\t%l0\t" ASM_COMMENT_START " fused"; -} - [(set_attr "type" "multi") - (set_attr "mode" "<MODE>")]) - -(define_insn "*jcc_fused_3" - [(set (pc) - (if_then_else - (match_operator 1 "ix86_comparison_uns_operator" - [(match_operand:SWI32 2 "nonimmediate_operand" "<r>,m,<r>") - (match_operand:SWI32 3 "<general_operand>" "<r><i>,<r>,m")]) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_FUSE_CMP_AND_BRANCH && !TARGET_64BIT - && !(MEM_P (operands[2]) - && (MEM_P (operands[3]) || CONST_INT_P (operands[3])))" -{ - return "cmp{<imodesuffix>}\t{%3, %2|%2, %3}\n\t" - "%+j%E1\t%l0\t" ASM_COMMENT_START " fused"; -} - [(set_attr "type" "multi") - (set_attr "mode" "<MODE>")]) - -(define_insn "*jcc_fused_4" - [(set (pc) - (if_then_else - (match_operator 1 "ix86_comparison_uns_operator" - [(match_operand:SWI32 2 "nonimmediate_operand" "<r>,m,<r>") - (match_operand:SWI32 3 "<general_operand>" "<r><i>,<r>,m")]) - (pc) - (label_ref (match_operand 0 "" ""))))] - "TARGET_FUSE_CMP_AND_BRANCH && !TARGET_64BIT - && !(MEM_P (operands[2]) - && (MEM_P (operands[3]) || CONST_INT_P (operands[3])))" -{ - return "cmp{<imodesuffix>}\t{%3, %2|%2, %3}\n\t" - "%+j%e1\t%l0\t" ASM_COMMENT_START " fused"; -} - [(set_attr "type" "multi") - (set_attr "mode" "<MODE>")]) - ;; In general it is not safe to assume too much about CCmode registers, ;; so simplify-rtx stops when it sees a second one. Under certain ;; conditions this is safe on x86, so help combine not create diff --git a/gcc/config/i386/t-cygming b/gcc/config/i386/t-cygming index c6e6cac7811..ecfe2d1d2a3 100644 --- a/gcc/config/i386/t-cygming +++ b/gcc/config/i386/t-cygming @@ -54,7 +54,6 @@ SHLIB_MAP = @shlib_map_file@ SHLIB_OBJS = @shlib_objs@ SHLIB_DIR = @multilib_dir@/shlib SHLIB_SLIBDIR_QUAL = @shlib_slibdir_qual@ -SHLIB_LC = -luser32 -lkernel32 -ladvapi32 -lshell32 SHLIB_LINK = $(LN_S) $(SHLIB_MAP) $(SHLIB_MAP).def && \ if [ ! -d $(SHLIB_DIR) ]; then \ @@ -65,8 +64,6 @@ SHLIB_LINK = $(LN_S) $(SHLIB_MAP) $(SHLIB_MAP).def && \ -Wl,--out-implib,$(SHLIB_DIR)/$(SHLIB_IMPLIB).tmp \ -o $(SHLIB_DIR)/$(SHLIB_SONAME).tmp @multilib_flags@ \ $(SHLIB_OBJS) $(SHLIB_LC) && \ - $(AR_FOR_TARGET) -r $(SHLIB_DIR)/$(SHLIB_IMPLIB).tmp \ - _chkstk.o _ctors.o gthr-win32.o && \ if [ -f $(SHLIB_DIR)/$(SHLIB_SONAME) ]; then \ mv -f $(SHLIB_DIR)/$(SHLIB_SONAME) \ $(SHLIB_DIR)/$(SHLIB_SONAME).backup; \ diff --git a/gcc/config/i386/t-cygwin b/gcc/config/i386/t-cygwin index 3715c0b450c..7433138d692 100644 --- a/gcc/config/i386/t-cygwin +++ b/gcc/config/i386/t-cygwin @@ -15,4 +15,4 @@ cygwin2.o: $(srcdir)/config/i386/cygwin2.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ $(srcdir)/config/i386/cygwin2.c # Cygwin-specific parts of LIB_SPEC -SHLIB_LC += -lcygwin +SHLIB_LC = -lcygwin -luser32 -lkernel32 -ladvapi32 -lshell32 diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 799570cc7ae..20532ba3de2 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -10377,6 +10377,7 @@ mips_issue_rate (void) case PROCESSOR_R5500: case PROCESSOR_R7000: case PROCESSOR_R9000: + case PROCESSOR_OCTEON: return 2; case PROCESSOR_SB1: @@ -10518,6 +10519,9 @@ mips_multipass_dfa_lookahead (void) if (TUNE_LOONGSON_2EF) return 4; + if (TUNE_OCTEON) + return 2; + return 0; } diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index effa34ba261..ab248692f56 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -281,6 +281,7 @@ enum mips_code_readable_setting { #define TUNE_MIPS6000 (mips_tune == PROCESSOR_R6000) #define TUNE_MIPS7000 (mips_tune == PROCESSOR_R7000) #define TUNE_MIPS9000 (mips_tune == PROCESSOR_R9000) +#define TUNE_OCTEON (mips_tune == PROCESSOR_OCTEON) #define TUNE_SB1 (mips_tune == PROCESSOR_SB1 \ || mips_tune == PROCESSOR_SB1A) diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 593fae30ba6..58d1fd6637f 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -935,10 +935,11 @@ (include "6000.md") (include "7000.md") (include "9000.md") +(include "loongson2ef.md") +(include "octeon.md") (include "sb1.md") (include "sr71k.md") (include "xlr.md") -(include "loongson2ef.md") (include "generic.md") ;; diff --git a/gcc/config/mips/octeon.md b/gcc/config/mips/octeon.md new file mode 100644 index 00000000000..0d94e6eecff --- /dev/null +++ b/gcc/config/mips/octeon.md @@ -0,0 +1,88 @@ +;; Octeon pipeline description. +;; 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 3, 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 COPYING3. If not see +;; <http://www.gnu.org/licenses/>. +;; Copyright (C) 2004, 2005, 2006 Cavium Networks. + + +;; Octeon is a dual-issue processor that can issue all instructions on +;; pipe0 and a subset on pipe1. + +(define_automaton "octeon_main, octeon_mult") + +(define_cpu_unit "octeon_pipe0" "octeon_main") +(define_cpu_unit "octeon_pipe1" "octeon_main") +(define_cpu_unit "octeon_mult" "octeon_mult") + +(define_insn_reservation "octeon_arith" 1 + (and (eq_attr "cpu" "octeon") + (eq_attr "type" "arith,const,logical,move,shift,signext,slt,nop")) + "octeon_pipe0 | octeon_pipe1") + +(define_insn_reservation "octeon_condmove" 2 + (and (eq_attr "cpu" "octeon") + (eq_attr "type" "condmove")) + "octeon_pipe0 | octeon_pipe1") + +(define_insn_reservation "octeon_load" 2 + (and (eq_attr "cpu" "octeon") + (eq_attr "type" "load,prefetch,mtc,mfc")) + "octeon_pipe0") + +(define_insn_reservation "octeon_store" 1 + (and (eq_attr "cpu" "octeon") + (eq_attr "type" "store")) + "octeon_pipe0") + +(define_insn_reservation "octeon_brj" 1 + (and (eq_attr "cpu" "octeon") + (eq_attr "type" "branch,jump,call,trap")) + "octeon_pipe0") + +(define_insn_reservation "octeon_imul3" 5 + (and (eq_attr "cpu" "octeon") + (eq_attr "type" "imul3,pop,clz")) + "(octeon_pipe0 | octeon_pipe1) + octeon_mult") + +(define_insn_reservation "octeon_imul" 2 + (and (eq_attr "cpu" "octeon") + (eq_attr "type" "imul,mthilo")) + "(octeon_pipe0 | octeon_pipe1) + octeon_mult, octeon_mult") + +(define_insn_reservation "octeon_mfhilo" 5 + (and (eq_attr "cpu" "octeon") + (eq_attr "type" "mfhilo")) + "(octeon_pipe0 | octeon_pipe1) + octeon_mult") + +(define_insn_reservation "octeon_imadd" 4 + (and (eq_attr "cpu" "octeon") + (eq_attr "type" "imadd")) + "(octeon_pipe0 | octeon_pipe1) + octeon_mult, octeon_mult*3") + +(define_insn_reservation "octeon_idiv" 72 + (and (eq_attr "cpu" "octeon") + (eq_attr "type" "idiv")) + "(octeon_pipe0 | octeon_pipe1) + octeon_mult, octeon_mult*71") + +;; Assume both pipes are needed for unknown and multiple-instruction +;; patterns. + +(define_insn_reservation "octeon_unknown" 1 + (and (eq_attr "cpu" "octeon") + (eq_attr "type" "unknown,multi")) + "octeon_pipe0 + octeon_pipe1") diff --git a/gcc/config/sparc/sparc-protos.h b/gcc/config/sparc/sparc-protos.h index 7c56925c01d..a15837fccc0 100644 --- a/gcc/config/sparc/sparc-protos.h +++ b/gcc/config/sparc/sparc-protos.h @@ -54,7 +54,8 @@ extern void sparc_output_scratch_registers (FILE *); extern enum machine_mode select_cc_mode (enum rtx_code, rtx, rtx); /* Define the function that build the compare insn for scc and bcc. */ extern rtx gen_compare_reg (enum rtx_code code); -extern void sparc_emit_float_lib_cmp (rtx, rtx, enum rtx_code); +extern rtx gen_compare_operator (enum rtx_code code); +extern enum rtx_code sparc_emit_float_lib_cmp (rtx, rtx, enum rtx_code); extern void sparc_emit_floatunsdi (rtx [2], enum machine_mode); extern void sparc_emit_fixunsdi (rtx [2], enum machine_mode); extern void emit_tfmode_binop (enum rtx_code, rtx *); diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index 0852cd94e79..fd566532067 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -2001,8 +2001,7 @@ select_cc_mode (enum rtx_code op, rtx x, rtx y ATTRIBUTE_UNUSED) } } -/* X and Y are two things to compare using CODE. Emit the compare insn and - return the rtx for the cc reg in the proper mode. */ +/* Emit the compare insn and return the CC reg for a CODE comparison. */ rtx gen_compare_reg (enum rtx_code code) @@ -2065,12 +2064,28 @@ gen_compare_reg (enum rtx_code code) else cc_reg = gen_rtx_REG (mode, SPARC_ICC_REG); - emit_insn (gen_rtx_SET (VOIDmode, cc_reg, - gen_rtx_COMPARE (mode, x, y))); + /* We shouldn't get there for TFmode if !TARGET_HARD_QUAD. If we do, this + will only result in an unrecognizable insn so no point in asserting. */ + emit_insn (gen_rtx_SET (VOIDmode, cc_reg, gen_rtx_COMPARE (mode, x, y))); return cc_reg; } +/* Same as above but return the whole compare operator. */ + +rtx +gen_compare_operator (enum rtx_code code) +{ + rtx cc_reg; + + if (GET_MODE (sparc_compare_op0) == TFmode && !TARGET_HARD_QUAD) + code + = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, code); + + cc_reg = gen_compare_reg (code); + return gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx); +} + /* This function is used for v9 only. CODE is the code for an Scc's comparison. OPERANDS[0] is the target of the Scc insn. @@ -6099,41 +6114,45 @@ output_cbranch (rtx op, rtx dest, int label, int reversed, int annul, } /* Emit a library call comparison between floating point X and Y. - COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). + COMPARISON is the operator to compare with (EQ, NE, GT, etc). + Return the new operator to be used in the comparison sequence. + TARGET_ARCH64 uses _Qp_* functions, which use pointers to TFmode values as arguments instead of the TFmode registers themselves, that's why we cannot call emit_float_lib_cmp. */ -void + +enum rtx_code sparc_emit_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison) { const char *qpfunc; rtx slot0, slot1, result, tem, tem2; enum machine_mode mode; + enum rtx_code new_comparison; switch (comparison) { case EQ: - qpfunc = (TARGET_ARCH64) ? "_Qp_feq" : "_Q_feq"; + qpfunc = (TARGET_ARCH64 ? "_Qp_feq" : "_Q_feq"); break; case NE: - qpfunc = (TARGET_ARCH64) ? "_Qp_fne" : "_Q_fne"; + qpfunc = (TARGET_ARCH64 ? "_Qp_fne" : "_Q_fne"); break; case GT: - qpfunc = (TARGET_ARCH64) ? "_Qp_fgt" : "_Q_fgt"; + qpfunc = (TARGET_ARCH64 ? "_Qp_fgt" : "_Q_fgt"); break; case GE: - qpfunc = (TARGET_ARCH64) ? "_Qp_fge" : "_Q_fge"; + qpfunc = (TARGET_ARCH64 ? "_Qp_fge" : "_Q_fge"); break; case LT: - qpfunc = (TARGET_ARCH64) ? "_Qp_flt" : "_Q_flt"; + qpfunc = (TARGET_ARCH64 ? "_Qp_flt" : "_Q_flt"); break; case LE: - qpfunc = (TARGET_ARCH64) ? "_Qp_fle" : "_Q_fle"; + qpfunc = (TARGET_ARCH64 ? "_Qp_fle" : "_Q_fle"); break; case ORDERED: @@ -6144,7 +6163,7 @@ sparc_emit_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison) case UNGE: case UNLE: case LTGT: - qpfunc = (TARGET_ARCH64) ? "_Qp_cmp" : "_Q_cmp"; + qpfunc = (TARGET_ARCH64 ? "_Qp_cmp" : "_Q_cmp"); break; default: @@ -6153,27 +6172,26 @@ sparc_emit_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison) if (TARGET_ARCH64) { - if (GET_CODE (x) != MEM) + if (MEM_P (x)) + slot0 = x; + else { slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0); emit_move_insn (slot0, x); } - else - slot0 = x; - if (GET_CODE (y) != MEM) + if (MEM_P (y)) + slot1 = y; + else { slot1 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0); emit_move_insn (slot1, y); } - else - slot1 = y; emit_library_call (gen_rtx_SYMBOL_REF (Pmode, qpfunc), LCT_NORMAL, DImode, 2, XEXP (slot0, 0), Pmode, XEXP (slot1, 0), Pmode); - mode = DImode; } else @@ -6181,7 +6199,6 @@ sparc_emit_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison) emit_library_call (gen_rtx_SYMBOL_REF (Pmode, qpfunc), LCT_NORMAL, SImode, 2, x, TFmode, y, TFmode); - mode = SImode; } @@ -6195,20 +6212,22 @@ sparc_emit_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison) switch (comparison) { default: - emit_cmp_insn (result, const0_rtx, NE, NULL_RTX, mode, 0); + new_comparison = NE; + emit_cmp_insn (result, const0_rtx, new_comparison, NULL_RTX, mode, 0); break; case ORDERED: case UNORDERED: - emit_cmp_insn (result, GEN_INT(3), comparison == UNORDERED ? EQ : NE, - NULL_RTX, mode, 0); + new_comparison = (comparison == UNORDERED ? EQ : NE); + emit_cmp_insn (result, GEN_INT(3), new_comparison, NULL_RTX, mode, 0); break; case UNGT: case UNGE: - emit_cmp_insn (result, const1_rtx, - comparison == UNGT ? GT : NE, NULL_RTX, mode, 0); + new_comparison = (comparison == UNGT ? GT : NE); + emit_cmp_insn (result, const1_rtx, new_comparison, NULL_RTX, mode, 0); break; case UNLE: - emit_cmp_insn (result, const2_rtx, NE, NULL_RTX, mode, 0); + new_comparison = NE; + emit_cmp_insn (result, const2_rtx, new_comparison, NULL_RTX, mode, 0); break; case UNLT: tem = gen_reg_rtx (mode); @@ -6216,7 +6235,8 @@ sparc_emit_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison) emit_insn (gen_andsi3 (tem, result, const1_rtx)); else emit_insn (gen_anddi3 (tem, result, const1_rtx)); - emit_cmp_insn (tem, const0_rtx, NE, NULL_RTX, mode, 0); + new_comparison = NE; + emit_cmp_insn (tem, const0_rtx, new_comparison, NULL_RTX, mode, 0); break; case UNEQ: case LTGT: @@ -6230,10 +6250,12 @@ sparc_emit_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison) emit_insn (gen_andsi3 (tem2, tem, const2_rtx)); else emit_insn (gen_anddi3 (tem2, tem, const2_rtx)); - emit_cmp_insn (tem2, const0_rtx, comparison == UNEQ ? EQ : NE, - NULL_RTX, mode, 0); + new_comparison = (comparison == UNEQ ? EQ : NE); + emit_cmp_insn (tem2, const0_rtx, new_comparison, NULL_RTX, mode, 0); break; } + + return new_comparison; } /* Generate an unsigned DImode to FP conversion. This is the same code diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md index bc29bcf819c..d0b73893945 100644 --- a/gcc/config/sparc/sparc.md +++ b/gcc/config/sparc/sparc.md @@ -621,8 +621,10 @@ } else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) { - sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ); - emit_jump_insn (gen_sne (operands[0])); + enum rtx_code code + = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ); + gcc_assert (code == NE); + emit_insn (gen_sne (operands[0])); DONE; } else if (TARGET_V9) @@ -673,8 +675,10 @@ } else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) { - sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE); - emit_jump_insn (gen_sne (operands[0])); + enum rtx_code code + = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE); + gcc_assert (code == NE); + emit_insn (gen_sne (operands[0])); DONE; } else if (TARGET_V9) @@ -693,8 +697,10 @@ { if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) { - sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT); - emit_jump_insn (gen_sne (operands[0])); + enum rtx_code code + = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT); + gcc_assert (code == NE); + emit_insn (gen_sne (operands[0])); DONE; } else if (TARGET_V9) @@ -713,8 +719,10 @@ { if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) { - sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT); - emit_jump_insn (gen_sne (operands[0])); + enum rtx_code code + = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT); + gcc_assert (code == NE); + emit_insn (gen_sne (operands[0])); DONE; } else if (TARGET_V9) @@ -733,8 +741,10 @@ { if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) { - sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE); - emit_jump_insn (gen_sne (operands[0])); + enum rtx_code code + = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE); + gcc_assert (code == NE); + emit_insn (gen_sne (operands[0])); DONE; } else if (TARGET_V9) @@ -753,8 +763,10 @@ { if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) { - sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE); - emit_jump_insn (gen_sne (operands[0])); + enum rtx_code code + = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE); + gcc_assert (code == NE); + emit_insn (gen_sne (operands[0])); DONE; } else if (TARGET_V9) @@ -1270,7 +1282,9 @@ } else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) { - sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ); + enum rtx_code code + = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ); + gcc_assert (code == NE); emit_jump_insn (gen_bne (operands[0])); DONE; } @@ -1293,7 +1307,9 @@ } else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) { - sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE); + enum rtx_code code + = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE); + gcc_assert (code == NE); emit_jump_insn (gen_bne (operands[0])); DONE; } @@ -1316,7 +1332,9 @@ } else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) { - sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT); + enum rtx_code code + = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT); + gcc_assert (code == NE); emit_jump_insn (gen_bne (operands[0])); DONE; } @@ -1349,7 +1367,9 @@ } else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) { - sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT); + enum rtx_code code + = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT); + gcc_assert (code == NE); emit_jump_insn (gen_bne (operands[0])); DONE; } @@ -1382,7 +1402,9 @@ } else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) { - sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE); + enum rtx_code code + = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE); + gcc_assert (code == NE); emit_jump_insn (gen_bne (operands[0])); DONE; } @@ -1415,7 +1437,9 @@ } else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) { - sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE); + enum rtx_code code + = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE); + gcc_assert (code == NE); emit_jump_insn (gen_bne (operands[0])); DONE; } @@ -1441,8 +1465,9 @@ { if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) { - sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, - UNORDERED); + enum rtx_code code + = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNORDERED); + gcc_assert (code == EQ); emit_jump_insn (gen_beq (operands[0])); DONE; } @@ -1458,7 +1483,9 @@ { if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) { - sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, ORDERED); + enum rtx_code code + = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, ORDERED); + gcc_assert (code == NE); emit_jump_insn (gen_bne (operands[0])); DONE; } @@ -1474,7 +1501,9 @@ { if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) { - sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNGT); + enum rtx_code code + = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNGT); + gcc_assert (code == GT); emit_jump_insn (gen_bgt (operands[0])); DONE; } @@ -1490,7 +1519,9 @@ { if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) { - sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNLT); + enum rtx_code code + = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNLT); + gcc_assert (code == NE); emit_jump_insn (gen_bne (operands[0])); DONE; } @@ -1506,7 +1537,9 @@ { if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) { - sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNEQ); + enum rtx_code code + = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNEQ); + gcc_assert (code == EQ); emit_jump_insn (gen_beq (operands[0])); DONE; } @@ -1522,7 +1555,9 @@ { if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) { - sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNGE); + enum rtx_code code + = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNGE); + gcc_assert (code == NE); emit_jump_insn (gen_bne (operands[0])); DONE; } @@ -1538,7 +1573,9 @@ { if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) { - sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNLE); + enum rtx_code code + = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNLE); + gcc_assert (code == NE); emit_jump_insn (gen_bne (operands[0])); DONE; } @@ -1554,7 +1591,9 @@ { if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) { - sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LTGT); + enum rtx_code code + = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LTGT); + gcc_assert (code == NE); emit_jump_insn (gen_bne (operands[0])); DONE; } @@ -3015,7 +3054,7 @@ }) -;; SPARC-V9 conditional move instructions. +;; SPARC-V9 conditional move instructions ;; We can handle larger constants here for some flavors, but for now we keep ;; it simple and only allow those constants supported by all flavors. @@ -3023,40 +3062,14 @@ ;; 3 contains the constant if one is present, but we handle either for ;; generality (sparc.c puts a constant in operand 2). -(define_expand "movqicc" - [(set (match_operand:QI 0 "register_operand" "") - (if_then_else:QI (match_operand 1 "comparison_operator" "") - (match_operand:QI 2 "arith10_operand" "") - (match_operand:QI 3 "arith10_operand" "")))] - "TARGET_V9" -{ - enum rtx_code code = GET_CODE (operands[1]); - - if (GET_MODE (sparc_compare_op0) == DImode - && ! TARGET_ARCH64) - FAIL; - - if (sparc_compare_op1 == const0_rtx - && GET_CODE (sparc_compare_op0) == REG - && GET_MODE (sparc_compare_op0) == DImode - && v9_regcmp_p (code)) - { - operands[1] = gen_rtx_fmt_ee (code, DImode, - sparc_compare_op0, sparc_compare_op1); - } - else - { - rtx cc_reg = gen_compare_reg (code); - operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx); - } -}) +(define_mode_iterator I [QI HI SI DI]) -(define_expand "movhicc" - [(set (match_operand:HI 0 "register_operand" "") - (if_then_else:HI (match_operand 1 "comparison_operator" "") - (match_operand:HI 2 "arith10_operand" "") - (match_operand:HI 3 "arith10_operand" "")))] - "TARGET_V9" +(define_expand "mov<I:mode>cc" + [(set (match_operand:I 0 "register_operand" "") + (if_then_else:I (match_operand 1 "comparison_operator" "") + (match_operand:I 2 "arith10_operand" "") + (match_operand:I 3 "arith10_operand" "")))] + "TARGET_V9 && !(<I:MODE>mode == DImode && TARGET_ARCH32)" { enum rtx_code code = GET_CODE (operands[1]); @@ -3068,72 +3081,18 @@ && GET_CODE (sparc_compare_op0) == REG && GET_MODE (sparc_compare_op0) == DImode && v9_regcmp_p (code)) - { - operands[1] = gen_rtx_fmt_ee (code, DImode, - sparc_compare_op0, sparc_compare_op1); - } - else - { - rtx cc_reg = gen_compare_reg (code); - operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx); - } -}) - -(define_expand "movsicc" - [(set (match_operand:SI 0 "register_operand" "") - (if_then_else:SI (match_operand 1 "comparison_operator" "") - (match_operand:SI 2 "arith10_operand" "") - (match_operand:SI 3 "arith10_operand" "")))] - "TARGET_V9" -{ - enum rtx_code code = GET_CODE (operands[1]); - enum machine_mode op0_mode = GET_MODE (sparc_compare_op0); - - if (sparc_compare_op1 == const0_rtx - && GET_CODE (sparc_compare_op0) == REG - && (TARGET_ARCH64 && op0_mode == DImode && v9_regcmp_p (code))) - { - operands[1] = gen_rtx_fmt_ee (code, op0_mode, - sparc_compare_op0, sparc_compare_op1); - } + operands[1] = gen_rtx_fmt_ee (code, DImode, sparc_compare_op0, const0_rtx); else - { - rtx cc_reg = gen_compare_reg (code); - operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), - cc_reg, const0_rtx); - } + operands[1] = gen_compare_operator (code); }) -(define_expand "movdicc" - [(set (match_operand:DI 0 "register_operand" "") - (if_then_else:DI (match_operand 1 "comparison_operator" "") - (match_operand:DI 2 "arith10_operand" "") - (match_operand:DI 3 "arith10_operand" "")))] - "TARGET_ARCH64" -{ - enum rtx_code code = GET_CODE (operands[1]); - - if (sparc_compare_op1 == const0_rtx - && GET_CODE (sparc_compare_op0) == REG - && GET_MODE (sparc_compare_op0) == DImode - && v9_regcmp_p (code)) - { - operands[1] = gen_rtx_fmt_ee (code, DImode, - sparc_compare_op0, sparc_compare_op1); - } - else - { - rtx cc_reg = gen_compare_reg (code); - operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), - cc_reg, const0_rtx); - } -}) +(define_mode_iterator F [SF DF TF]) -(define_expand "movsfcc" - [(set (match_operand:SF 0 "register_operand" "") - (if_then_else:SF (match_operand 1 "comparison_operator" "") - (match_operand:SF 2 "register_operand" "") - (match_operand:SF 3 "register_operand" "")))] +(define_expand "mov<F:mode>cc" + [(set (match_operand:F 0 "register_operand" "") + (if_then_else:F (match_operand 1 "comparison_operator" "") + (match_operand:F 2 "register_operand" "") + (match_operand:F 3 "register_operand" "")))] "TARGET_V9 && TARGET_FPU" { enum rtx_code code = GET_CODE (operands[1]); @@ -3146,160 +3105,73 @@ && GET_CODE (sparc_compare_op0) == REG && GET_MODE (sparc_compare_op0) == DImode && v9_regcmp_p (code)) - { - operands[1] = gen_rtx_fmt_ee (code, DImode, - sparc_compare_op0, sparc_compare_op1); - } + operands[1] = gen_rtx_fmt_ee (code, DImode, sparc_compare_op0, const0_rtx); else - { - rtx cc_reg = gen_compare_reg (code); - operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx); - } + operands[1] = gen_compare_operator (code); }) -(define_expand "movdfcc" - [(set (match_operand:DF 0 "register_operand" "") - (if_then_else:DF (match_operand 1 "comparison_operator" "") - (match_operand:DF 2 "register_operand" "") - (match_operand:DF 3 "register_operand" "")))] - "TARGET_V9 && TARGET_FPU" -{ - enum rtx_code code = GET_CODE (operands[1]); - - if (GET_MODE (sparc_compare_op0) == DImode - && ! TARGET_ARCH64) - FAIL; - - if (sparc_compare_op1 == const0_rtx - && GET_CODE (sparc_compare_op0) == REG - && GET_MODE (sparc_compare_op0) == DImode - && v9_regcmp_p (code)) - { - operands[1] = gen_rtx_fmt_ee (code, DImode, - sparc_compare_op0, sparc_compare_op1); - } - else - { - rtx cc_reg = gen_compare_reg (code); - operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx); - } -}) - -(define_expand "movtfcc" - [(set (match_operand:TF 0 "register_operand" "") - (if_then_else:TF (match_operand 1 "comparison_operator" "") - (match_operand:TF 2 "register_operand" "") - (match_operand:TF 3 "register_operand" "")))] - "TARGET_V9 && TARGET_FPU" -{ - enum rtx_code code = GET_CODE (operands[1]); - - if (GET_MODE (sparc_compare_op0) == DImode - && ! TARGET_ARCH64) - FAIL; - - if (sparc_compare_op1 == const0_rtx - && GET_CODE (sparc_compare_op0) == REG - && GET_MODE (sparc_compare_op0) == DImode - && v9_regcmp_p (code)) - { - operands[1] = gen_rtx_fmt_ee (code, DImode, - sparc_compare_op0, sparc_compare_op1); - } - else - { - rtx cc_reg = gen_compare_reg (code); - operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx); - } -}) - -;; Conditional move define_insns. - -(define_insn "*movqi_cc_sp64" - [(set (match_operand:QI 0 "register_operand" "=r,r") - (if_then_else:QI (match_operator 1 "comparison_operator" - [(match_operand 2 "icc_or_fcc_register_operand" "X,X") - (const_int 0)]) - (match_operand:QI 3 "arith11_operand" "rL,0") - (match_operand:QI 4 "arith11_operand" "0,rL")))] - "TARGET_V9" - "@ - mov%C1\t%x2, %3, %0 - mov%c1\t%x2, %4, %0" - [(set_attr "type" "cmove")]) - -(define_insn "*movhi_cc_sp64" - [(set (match_operand:HI 0 "register_operand" "=r,r") - (if_then_else:HI (match_operator 1 "comparison_operator" - [(match_operand 2 "icc_or_fcc_register_operand" "X,X") - (const_int 0)]) - (match_operand:HI 3 "arith11_operand" "rL,0") - (match_operand:HI 4 "arith11_operand" "0,rL")))] - "TARGET_V9" - "@ - mov%C1\t%x2, %3, %0 - mov%c1\t%x2, %4, %0" - [(set_attr "type" "cmove")]) - -(define_insn "*movsi_cc_sp64" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (if_then_else:SI (match_operator 1 "comparison_operator" - [(match_operand 2 "icc_or_fcc_register_operand" "X,X") - (const_int 0)]) - (match_operand:SI 3 "arith11_operand" "rL,0") - (match_operand:SI 4 "arith11_operand" "0,rL")))] - "TARGET_V9" - "@ - mov%C1\t%x2, %3, %0 - mov%c1\t%x2, %4, %0" - [(set_attr "type" "cmove")]) +;; Conditional move define_insns -(define_insn "*movdi_cc_sp64" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (if_then_else:DI (match_operator 1 "comparison_operator" - [(match_operand 2 "icc_or_fcc_register_operand" "X,X") - (const_int 0)]) - (match_operand:DI 3 "arith11_operand" "rL,0") - (match_operand:DI 4 "arith11_operand" "0,rL")))] - "TARGET_ARCH64" +(define_insn "*mov<I:mode>_cc_v9" + [(set (match_operand:I 0 "register_operand" "=r,r") + (if_then_else:I (match_operator 1 "comparison_operator" + [(match_operand 2 "icc_or_fcc_register_operand" "X,X") + (const_int 0)]) + (match_operand:I 3 "arith11_operand" "rL,0") + (match_operand:I 4 "arith11_operand" "0,rL")))] + "TARGET_V9 && !(<I:MODE>mode == DImode && TARGET_ARCH32)" "@ mov%C1\t%x2, %3, %0 mov%c1\t%x2, %4, %0" [(set_attr "type" "cmove")]) -(define_insn "*movdi_cc_sp64_trunc" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (if_then_else:SI (match_operator 1 "comparison_operator" - [(match_operand 2 "icc_or_fcc_register_operand" "X,X") +(define_insn "*mov<I:mode>_cc_reg_sp64" + [(set (match_operand:I 0 "register_operand" "=r,r") + (if_then_else:I (match_operator 1 "v9_register_compare_operator" + [(match_operand:DI 2 "register_operand" "r,r") (const_int 0)]) - (match_operand:SI 3 "arith11_operand" "rL,0") - (match_operand:SI 4 "arith11_operand" "0,rL")))] + (match_operand:I 3 "arith10_operand" "rM,0") + (match_operand:I 4 "arith10_operand" "0,rM")))] "TARGET_ARCH64" "@ - mov%C1\t%x2, %3, %0 - mov%c1\t%x2, %4, %0" + movr%D1\t%2, %r3, %0 + movr%d1\t%2, %r4, %0" [(set_attr "type" "cmove")]) -(define_insn "*movsf_cc_sp64" +(define_insn "*movsf_cc_v9" [(set (match_operand:SF 0 "register_operand" "=f,f") (if_then_else:SF (match_operator 1 "comparison_operator" [(match_operand 2 "icc_or_fcc_register_operand" "X,X") (const_int 0)]) - (match_operand:SF 3 "register_operand" "f,0") - (match_operand:SF 4 "register_operand" "0,f")))] + (match_operand:SF 3 "register_operand" "f,0") + (match_operand:SF 4 "register_operand" "0,f")))] "TARGET_V9 && TARGET_FPU" "@ fmovs%C1\t%x2, %3, %0 fmovs%c1\t%x2, %4, %0" [(set_attr "type" "fpcmove")]) -(define_insn "movdf_cc_sp64" +(define_insn "*movsf_cc_reg_sp64" + [(set (match_operand:SF 0 "register_operand" "=f,f") + (if_then_else:SF (match_operator 1 "v9_register_compare_operator" + [(match_operand:DI 2 "register_operand" "r,r") + (const_int 0)]) + (match_operand:SF 3 "register_operand" "f,0") + (match_operand:SF 4 "register_operand" "0,f")))] + "TARGET_ARCH64 && TARGET_FPU" + "@ + fmovrs%D1\t%2, %3, %0 + fmovrs%d1\t%2, %4, %0" + [(set_attr "type" "fpcrmove")]) + +;; Named because invoked by movtf_cc_v9 +(define_insn "movdf_cc_v9" [(set (match_operand:DF 0 "register_operand" "=e,e") (if_then_else:DF (match_operator 1 "comparison_operator" [(match_operand 2 "icc_or_fcc_register_operand" "X,X") (const_int 0)]) - (match_operand:DF 3 "register_operand" "e,0") - (match_operand:DF 4 "register_operand" "0,e")))] + (match_operand:DF 3 "register_operand" "e,0") + (match_operand:DF 4 "register_operand" "0,e")))] "TARGET_V9 && TARGET_FPU" "@ fmovd%C1\t%x2, %3, %0 @@ -3307,26 +3179,54 @@ [(set_attr "type" "fpcmove") (set_attr "fptype" "double")]) -(define_insn "*movtf_cc_hq_sp64" +;; Named because invoked by movtf_cc_reg_sp64 +(define_insn "movdf_cc_reg_sp64" + [(set (match_operand:DF 0 "register_operand" "=e,e") + (if_then_else:DF (match_operator 1 "v9_register_compare_operator" + [(match_operand:DI 2 "register_operand" "r,r") + (const_int 0)]) + (match_operand:DF 3 "register_operand" "e,0") + (match_operand:DF 4 "register_operand" "0,e")))] + "TARGET_ARCH64 && TARGET_FPU" + "@ + fmovrd%D1\t%2, %3, %0 + fmovrd%d1\t%2, %4, %0" + [(set_attr "type" "fpcrmove") + (set_attr "fptype" "double")]) + +(define_insn "*movtf_cc_hq_v9" [(set (match_operand:TF 0 "register_operand" "=e,e") (if_then_else:TF (match_operator 1 "comparison_operator" [(match_operand 2 "icc_or_fcc_register_operand" "X,X") (const_int 0)]) - (match_operand:TF 3 "register_operand" "e,0") - (match_operand:TF 4 "register_operand" "0,e")))] + (match_operand:TF 3 "register_operand" "e,0") + (match_operand:TF 4 "register_operand" "0,e")))] "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD" "@ fmovq%C1\t%x2, %3, %0 fmovq%c1\t%x2, %4, %0" [(set_attr "type" "fpcmove")]) -(define_insn_and_split "*movtf_cc_sp64" +(define_insn "*movtf_cc_reg_hq_sp64" + [(set (match_operand:TF 0 "register_operand" "=e,e") + (if_then_else:TF (match_operator 1 "v9_register_compare_operator" + [(match_operand:DI 2 "register_operand" "r,r") + (const_int 0)]) + (match_operand:TF 3 "register_operand" "e,0") + (match_operand:TF 4 "register_operand" "0,e")))] + "TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD" + "@ + fmovrq%D1\t%2, %3, %0 + fmovrq%d1\t%2, %4, %0" + [(set_attr "type" "fpcrmove")]) + +(define_insn_and_split "*movtf_cc_v9" [(set (match_operand:TF 0 "register_operand" "=e,e") (if_then_else:TF (match_operator 1 "comparison_operator" [(match_operand 2 "icc_or_fcc_register_operand" "X,X") (const_int 0)]) - (match_operand:TF 3 "register_operand" "e,0") - (match_operand:TF 4 "register_operand" "0,e")))] + (match_operand:TF 3 "register_operand" "e,0") + (match_operand:TF 4 "register_operand" "0,e")))] "TARGET_V9 && TARGET_FPU && !TARGET_HARD_QUAD" "#" "&& reload_completed" @@ -3351,117 +3251,25 @@ if ((third && reg_overlap_mentioned_p (dest1, srcb2)) || (!third && reg_overlap_mentioned_p (dest1, srca2))) { - emit_insn (gen_movdf_cc_sp64 (dest2, operands[1], operands[2], srca2, srcb2)); - emit_insn (gen_movdf_cc_sp64 (dest1, operands[1], operands[2], srca1, srcb1)); + emit_insn (gen_movdf_cc_v9 (dest2, operands[1], operands[2], srca2, srcb2)); + emit_insn (gen_movdf_cc_v9 (dest1, operands[1], operands[2], srca1, srcb1)); } else { - emit_insn (gen_movdf_cc_sp64 (dest1, operands[1], operands[2], srca1, srcb1)); - emit_insn (gen_movdf_cc_sp64 (dest2, operands[1], operands[2], srca2, srcb2)); + emit_insn (gen_movdf_cc_v9 (dest1, operands[1], operands[2], srca1, srcb1)); + emit_insn (gen_movdf_cc_v9 (dest2, operands[1], operands[2], srca2, srcb2)); } DONE; } [(set_attr "length" "2")]) -(define_insn "*movqi_cc_reg_sp64" - [(set (match_operand:QI 0 "register_operand" "=r,r") - (if_then_else:QI (match_operator 1 "v9_register_compare_operator" - [(match_operand:DI 2 "register_operand" "r,r") - (const_int 0)]) - (match_operand:QI 3 "arith10_operand" "rM,0") - (match_operand:QI 4 "arith10_operand" "0,rM")))] - "TARGET_ARCH64" - "@ - movr%D1\t%2, %r3, %0 - movr%d1\t%2, %r4, %0" - [(set_attr "type" "cmove")]) - -(define_insn "*movhi_cc_reg_sp64" - [(set (match_operand:HI 0 "register_operand" "=r,r") - (if_then_else:HI (match_operator 1 "v9_register_compare_operator" - [(match_operand:DI 2 "register_operand" "r,r") - (const_int 0)]) - (match_operand:HI 3 "arith10_operand" "rM,0") - (match_operand:HI 4 "arith10_operand" "0,rM")))] - "TARGET_ARCH64" - "@ - movr%D1\t%2, %r3, %0 - movr%d1\t%2, %r4, %0" - [(set_attr "type" "cmove")]) - -(define_insn "*movsi_cc_reg_sp64" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (if_then_else:SI (match_operator 1 "v9_register_compare_operator" - [(match_operand:DI 2 "register_operand" "r,r") - (const_int 0)]) - (match_operand:SI 3 "arith10_operand" "rM,0") - (match_operand:SI 4 "arith10_operand" "0,rM")))] - "TARGET_ARCH64" - "@ - movr%D1\t%2, %r3, %0 - movr%d1\t%2, %r4, %0" - [(set_attr "type" "cmove")]) - -(define_insn "*movdi_cc_reg_sp64" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (if_then_else:DI (match_operator 1 "v9_register_compare_operator" - [(match_operand:DI 2 "register_operand" "r,r") - (const_int 0)]) - (match_operand:DI 3 "arith10_operand" "rM,0") - (match_operand:DI 4 "arith10_operand" "0,rM")))] - "TARGET_ARCH64" - "@ - movr%D1\t%2, %r3, %0 - movr%d1\t%2, %r4, %0" - [(set_attr "type" "cmove")]) - -(define_insn "*movsf_cc_reg_sp64" - [(set (match_operand:SF 0 "register_operand" "=f,f") - (if_then_else:SF (match_operator 1 "v9_register_compare_operator" - [(match_operand:DI 2 "register_operand" "r,r") - (const_int 0)]) - (match_operand:SF 3 "register_operand" "f,0") - (match_operand:SF 4 "register_operand" "0,f")))] - "TARGET_ARCH64 && TARGET_FPU" - "@ - fmovrs%D1\t%2, %3, %0 - fmovrs%d1\t%2, %4, %0" - [(set_attr "type" "fpcrmove")]) - -(define_insn "movdf_cc_reg_sp64" - [(set (match_operand:DF 0 "register_operand" "=e,e") - (if_then_else:DF (match_operator 1 "v9_register_compare_operator" - [(match_operand:DI 2 "register_operand" "r,r") - (const_int 0)]) - (match_operand:DF 3 "register_operand" "e,0") - (match_operand:DF 4 "register_operand" "0,e")))] - "TARGET_ARCH64 && TARGET_FPU" - "@ - fmovrd%D1\t%2, %3, %0 - fmovrd%d1\t%2, %4, %0" - [(set_attr "type" "fpcrmove") - (set_attr "fptype" "double")]) - -(define_insn "*movtf_cc_reg_hq_sp64" - [(set (match_operand:TF 0 "register_operand" "=e,e") - (if_then_else:TF (match_operator 1 "v9_register_compare_operator" - [(match_operand:DI 2 "register_operand" "r,r") - (const_int 0)]) - (match_operand:TF 3 "register_operand" "e,0") - (match_operand:TF 4 "register_operand" "0,e")))] - "TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD" - "@ - fmovrq%D1\t%2, %3, %0 - fmovrq%d1\t%2, %4, %0" - [(set_attr "type" "fpcrmove")]) - (define_insn_and_split "*movtf_cc_reg_sp64" [(set (match_operand:TF 0 "register_operand" "=e,e") (if_then_else:TF (match_operator 1 "v9_register_compare_operator" [(match_operand:DI 2 "register_operand" "r,r") (const_int 0)]) - (match_operand:TF 3 "register_operand" "e,0") - (match_operand:TF 4 "register_operand" "0,e")))] + (match_operand:TF 3 "register_operand" "e,0") + (match_operand:TF 4 "register_operand" "0,e")))] "TARGET_ARCH64 && TARGET_FPU && ! TARGET_HARD_QUAD" "#" "&& reload_completed" diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md index 29119ed16bb..abaf29d7333 100644 --- a/gcc/config/xtensa/xtensa.md +++ b/gcc/config/xtensa/xtensa.md @@ -898,13 +898,22 @@ rtx lit, scratch; unsigned word_off, byte_off; - gcc_assert (GET_CODE (operands[1]) == SUBREG); - lit = SUBREG_REG (operands[1]); - scratch = operands[2]; - word_off = SUBREG_BYTE (operands[1]) & ~(UNITS_PER_WORD - 1); - byte_off = SUBREG_BYTE (operands[1]) - word_off; + if (MEM_P (operands[1])) + { + lit = operands[1]; + word_off = 0; + byte_off = 0; + } + else + { + gcc_assert (GET_CODE (operands[1]) == SUBREG); + lit = SUBREG_REG (operands[1]); + word_off = SUBREG_BYTE (operands[1]) & ~(UNITS_PER_WORD - 1); + byte_off = SUBREG_BYTE (operands[1]) - word_off; + } lit = adjust_address (lit, SImode, word_off); + scratch = operands[2]; emit_insn (gen_movsi (scratch, lit)); emit_insn (gen_mov<mode> (operands[0], gen_rtx_SUBREG (<MODE>mode, scratch, byte_off))); diff --git a/gcc/doc/gccint.texi b/gcc/doc/gccint.texi index 6acc2d28190..1d127cb7f67 100644 --- a/gcc/doc/gccint.texi +++ b/gcc/doc/gccint.texi @@ -110,8 +110,10 @@ Additional tutorial information is linked to from * Passes:: Order of passes, what they do, and what each file is for. * Trees:: The source representation used by the C and C++ front ends. * RTL:: The intermediate representation that most passes work on. +* GENERIC:: Language-independent representation generated by Front Ends +* GIMPLE:: Tuple representation used by Tree SSA optimizers +* Tree SSA:: Analysis and optimization of GIMPLE * Control Flow:: Maintaining and manipulating the control flow graph. -* Tree SSA:: Analysis and optimization of the tree representation. * MELT:: the Middle End Lisp Translator. * Loop Analysis and Representation:: Analysis and representation of loops * Machine Desc:: How to write machine description instruction patterns. @@ -143,10 +145,12 @@ Additional tutorial information is linked to from @include options.texi @include passes.texi @include c-tree.texi +@include rtl.texi +@include generic.texi +@include gimple.texi @include tree-ssa.texi @include melt.texi @include loop.texi -@include rtl.texi @include cfg.texi @include md.texi @include tm.texi diff --git a/gcc/doc/generic.texi b/gcc/doc/generic.texi new file mode 100644 index 00000000000..14284cc397e --- /dev/null +++ b/gcc/doc/generic.texi @@ -0,0 +1,179 @@ +@c Copyright (c) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. +@c Free Software Foundation, Inc. +@c This is part of the GCC manual. +@c For copying conditions, see the file gcc.texi. + +@c --------------------------------------------------------------------- +@c GENERIC +@c --------------------------------------------------------------------- + +@node GENERIC +@chapter GENERIC +@cindex GENERIC + +The purpose of GENERIC is simply to provide a +language-independent way of representing an entire function in +trees. To this end, it was necessary to add a few new tree codes +to the back end, but most everything was already there. If you +can express it with the codes in @code{gcc/tree.def}, it's +GENERIC@. + +Early on, there was a great deal of debate about how to think +about statements in a tree IL@. In GENERIC, a statement is +defined as any expression whose value, if any, is ignored. A +statement will always have @code{TREE_SIDE_EFFECTS} set (or it +will be discarded), but a non-statement expression may also have +side effects. A @code{CALL_EXPR}, for instance. + +It would be possible for some local optimizations to work on the +GENERIC form of a function; indeed, the adapted tree inliner +works fine on GENERIC, but the current compiler performs inlining +after lowering to GIMPLE (a restricted form described in the next +section). Indeed, currently the frontends perform this lowering +before handing off to @code{tree_rest_of_compilation}, but this +seems inelegant. + +If necessary, a front end can use some language-dependent tree +codes in its GENERIC representation, so long as it provides a +hook for converting them to GIMPLE and doesn't expect them to +work with any (hypothetical) optimizers that run before the +conversion to GIMPLE@. The intermediate representation used while +parsing C and C++ looks very little like GENERIC, but the C and +C++ gimplifier hooks are perfectly happy to take it as input and +spit out GIMPLE@. + +@menu +* Statements:: +@end menu + +@node Statements +@section Statements +@cindex Statements + +Most statements in GIMPLE are assignment statements, represented by +@code{GIMPLE_ASSIGN}. No other C expressions can appear at statement level; +a reference to a volatile object is converted into a +@code{GIMPLE_ASSIGN}. + +There are also several varieties of complex statements. + +@menu +* Blocks:: +* Statement Sequences:: +* Empty Statements:: +* Jumps:: +* Cleanups:: +@end menu + +@node Blocks +@subsection Blocks +@cindex Blocks + +Block scopes and the variables they declare in GENERIC are +expressed using the @code{BIND_EXPR} code, which in previous +versions of GCC was primarily used for the C statement-expression +extension. + +Variables in a block are collected into @code{BIND_EXPR_VARS} in +declaration order. Any runtime initialization is moved out of +@code{DECL_INITIAL} and into a statement in the controlled block. +When gimplifying from C or C++, this initialization replaces the +@code{DECL_STMT}. + +Variable-length arrays (VLAs) complicate this process, as their +size often refers to variables initialized earlier in the block. +To handle this, we currently split the block at that point, and +move the VLA into a new, inner @code{BIND_EXPR}. This strategy +may change in the future. + +A C++ program will usually contain more @code{BIND_EXPR}s than +there are syntactic blocks in the source code, since several C++ +constructs have implicit scopes associated with them. On the +other hand, although the C++ front end uses pseudo-scopes to +handle cleanups for objects with destructors, these don't +translate into the GIMPLE form; multiple declarations at the same +level use the same @code{BIND_EXPR}. + +@node Statement Sequences +@subsection Statement Sequences +@cindex Statement Sequences + +Multiple statements at the same nesting level are collected into +a @code{STATEMENT_LIST}. Statement lists are modified and +traversed using the interface in @samp{tree-iterator.h}. + +@node Empty Statements +@subsection Empty Statements +@cindex Empty Statements + +Whenever possible, statements with no effect are discarded. But +if they are nested within another construct which cannot be +discarded for some reason, they are instead replaced with an +empty statement, generated by @code{build_empty_stmt}. +Initially, all empty statements were shared, after the pattern of +the Java front end, but this caused a lot of trouble in practice. + +An empty statement is represented as @code{(void)0}. + +@node Jumps +@subsection Jumps +@cindex Jumps + +Other jumps are expressed by either @code{GOTO_EXPR} or +@code{RETURN_EXPR}. + +The operand of a @code{GOTO_EXPR} must be either a label or a +variable containing the address to jump to. + +The operand of a @code{RETURN_EXPR} is either @code{NULL_TREE}, +@code{RESULT_DECL}, or a @code{MODIFY_EXPR} which sets the return +value. It would be nice to move the @code{MODIFY_EXPR} into a +separate statement, but the special return semantics in +@code{expand_return} make that difficult. It may still happen in +the future, perhaps by moving most of that logic into +@code{expand_assignment}. + +@node Cleanups +@subsection Cleanups +@cindex Cleanups + +Destructors for local C++ objects and similar dynamic cleanups are +represented in GIMPLE by a @code{TRY_FINALLY_EXPR}. +@code{TRY_FINALLY_EXPR} has two operands, both of which are a sequence +of statements to execute. The first sequence is executed. When it +completes the second sequence is executed. + +The first sequence may complete in the following ways: + +@enumerate + +@item Execute the last statement in the sequence and fall off the +end. + +@item Execute a goto statement (@code{GOTO_EXPR}) to an ordinary +label outside the sequence. + +@item Execute a return statement (@code{RETURN_EXPR}). + +@item Throw an exception. This is currently not explicitly represented in +GIMPLE. + +@end enumerate + +The second sequence is not executed if the first sequence completes by +calling @code{setjmp} or @code{exit} or any other function that does +not return. The second sequence is also not executed if the first +sequence completes via a non-local goto or a computed goto (in general +the compiler does not know whether such a goto statement exits the +first sequence or not, so we assume that it doesn't). + +After the second sequence is executed, if it completes normally by +falling off the end, execution continues wherever the first sequence +would have continued, by falling off the end, or doing a goto, etc. + +@code{TRY_FINALLY_EXPR} complicates the flow graph, since the cleanup +needs to appear on every edge out of the controlled block; this +reduces the freedom to move code across these edges. Therefore, the +EH lowering pass which runs before most of the optimization passes +eliminates these expressions by explicitly adding the cleanup to each +edge. Rethrowing the exception is represented using @code{RESX_EXPR}. diff --git a/gcc/doc/gimple.texi b/gcc/doc/gimple.texi new file mode 100644 index 00000000000..8277a8ca715 --- /dev/null +++ b/gcc/doc/gimple.texi @@ -0,0 +1,2498 @@ +@c Copyright (c) 2008 Free Software Foundation, Inc. +@c Free Software Foundation, Inc. +@c This is part of the GCC manual. +@c For copying conditions, see the file gcc.texi. + +@node GIMPLE +@chapter GIMPLE +@cindex GIMPLE + +GIMPLE is a three-address representation derived from GENERIC by +breaking down GENERIC expressions into tuples of no more than 3 +operands (with some exceptions like function calls). GIMPLE was +heavily influenced by the SIMPLE IL used by the McCAT compiler +project at McGill University, though we have made some different +choices. For one thing, SIMPLE doesn't support @code{goto}. + +Temporaries are introduced to hold intermediate values needed to +compute complex expressions. Additionally, all the control +structures used in GENERIC are lowered into conditional jumps, +lexical scopes are removed and exception regions are converted +into an on the side exception region tree. + +The compiler pass which converts GENERIC into GIMPLE is referred to as +the @samp{gimplifier}. The gimplifier works recursively, generating +GIMPLE tuples out of the original GENERIC expressions. + +One of the early implementation strategies used for the GIMPLE +representation was to use the same internal data structures used +by front ends to represent parse trees. This simplified +implementation because we could leverage existing functionality +and interfaces. However, GIMPLE is a much more restrictive +representation than abstract syntax trees (AST), therefore it +does not require the full structural complexity provided by the +main tree data structure. + +The GENERIC representation of a function is stored in the +@code{DECL_SAVED_TREE} field of the associated @code{FUNCTION_DECL} +tree node. It is converted to GIMPLE by a call to +@code{gimplify_function_tree}. + +If a front end wants to include language-specific tree codes in the tree +representation which it provides to the back end, it must provide a +definition of @code{LANG_HOOKS_GIMPLIFY_EXPR} which knows how to +convert the front end trees to GIMPLE@. Usually such a hook will involve +much of the same code for expanding front end trees to RTL@. This function +can return fully lowered GIMPLE, or it can return GENERIC trees and let the +main gimplifier lower them the rest of the way; this is often simpler. +GIMPLE that is not fully lowered is known as ``High GIMPLE'' and +consists of the IL before the pass @code{pass_lower_cf}. High GIMPLE +contains some container statements like lexical scopes +(represented by @code{GIMPLE_BIND}) and nested expressions (e.g., +@code{GIMPLE_TRY}), while ``Low GIMPLE'' exposes all of the +implicit jumps for control and exception expressions directly in +the IL and EH region trees. + +The C and C++ front ends currently convert directly from front end +trees to GIMPLE, and hand that off to the back end rather than first +converting to GENERIC@. Their gimplifier hooks know about all the +@code{_STMT} nodes and how to convert them to GENERIC forms. There +was some work done on a genericization pass which would run first, but +the existence of @code{STMT_EXPR} meant that in order to convert all +of the C statements into GENERIC equivalents would involve walking the +entire tree anyway, so it was simpler to lower all the way. This +might change in the future if someone writes an optimization pass +which would work better with higher-level trees, but currently the +optimizers all expect GIMPLE@. + +You can request to dump a C-like representation of the GIMPLE form +with the flag @option{-fdump-tree-gimple}. + +@menu +* Tuple representation:: +* GIMPLE instruction set:: +* GIMPLE Exception Handling:: +* Temporaries:: +* Operands:: +* Manipulating GIMPLE statements:: +* Tuple specific accessors:: +* GIMPLE sequences:: +* Sequence iterators:: +* Adding a new GIMPLE statement code:: +* Statement and operand traversals:: +@end menu + +@node Tuple representation +@section Tuple representation +@cindex tuples + +GIMPLE instructions are tuples of variable size divided in two +groups: a header describing the instruction and its locations, +and a variable length body with all the operands. Tuples are +organized into a hierarchy with 3 main classes of tuples. + +@subsection @code{gimple_statement_base} (gsbase) +@cindex gimple_statement_base + +This is the root of the hierarchy, it holds basic information +needed by most GIMPLE statements. There are some fields that +may not be relevant to every GIMPLE statement, but those were +moved into the base structure to take advantage of holes left by +other fields (thus making the structure more compact). The +structure takes 4 words (32 bytes) on 64 bit hosts: + +@multitable {@code{references_memory_p}} {Size (bits)} +@item Field @tab Size (bits) +@item @code{code} @tab 8 +@item @code{subcode} @tab 16 +@item @code{no_warning} @tab 1 +@item @code{visited} @tab 1 +@item @code{nontemporal_move} @tab 1 +@item @code{plf} @tab 2 +@item @code{modifed} @tab 1 +@item @code{has_volatile_ops} @tab 1 +@item @code{references_memory_p} @tab 1 +@item @code{uid} @tab 32 +@item @code{location} @tab 32 +@item @code{num_ops} @tab 32 +@item @code{bb} @tab 64 +@item @code{block} @tab 63 +@item Total size @tab 32 bytes +@end multitable + +@itemize @bullet +@item @code{code} +Main identifier for a GIMPLE instruction. + +@item @code{subcode} +Used to distinguish different variants of the same basic +instruction or provide flags applicable to a given code. The +@code{subcode} flags field has different uses depending on the code of +the instruction, but mostly it distinguishes instructions of the +same family. The most prominent use of this field is in +assignments, where subcode indicates the operation done on the +RHS of the assignment. For example, a = b + c is encoded as +@code{GIMPLE_ASSIGN <PLUS_EXPR, a, b, c>}. + +@item @code{no_warning} +Bitflag to indicate whether a warning has already been issued on +this statement. + +@item @code{visited} +General purpose ``visited'' marker. Set and cleared by each pass +when needed. + +@item @code{nontemporal_move} +Bitflag used in assignments that represent non-temporal moves. +Although this bitflag is only used in assignments, it was moved +into the base to take advantage of the bit holes left by the +previous fields. + +@item @code{plf} +Pass Local Flags. This 2-bit mask can be used as general purpose +markers by any pass. Passes are responsible for clearing and +setting these two flags accordingly. + +@item @code{modified} +Bitflag to indicate whether the statement has been modified. +Used mainly by the operand scanner to determine when to re-scan a +statement for operands. + +@item @code{has_volatile_ops} +Bitflag to indicate whether this statement contains operands that +have been marked volatile. + +@item @code{references_memory_p} +Bitflag to indicate whether this statement contains memory +references (i.e., its operands are either global variables, or +pointer dereferences or anything that must reside in memory). + +@item @code{uid} +This is an unsigned integer used by passes that want to assign +IDs to every statement. These IDs must be assigned and used by +each pass. + +@item @code{location} +This is a @code{location_t} identifier to specify source code +location for this statement. It is inherited from the front +end. + +@item @code{num_ops} +Number of operands that this statement has. This specifies the +size of the operand vector embedded in the tuple. Only used in +some tuples, but it is declared in the base tuple to take +advantage of the 32-bit hole left by the previous fields. + +@item @code{bb} +Basic block holding the instruction. + +@item @code{block} +Lexical block holding this statement. Also used for debug +information generation. +@end itemize + +@subsection @code{gimple_statement_with_ops} +@cindex gimple_statement_with_ops + +This tuple is actually split in two: +@code{gimple_statement_with_ops_base} and +@code{gimple_statement_with_ops}. This is needed to accommodate the +way the operand vector is allocated. The operand vector is +defined to be an array of 1 element. So, to allocate a dynamic +number of operands, the memory allocator (@code{gimple_alloc}) simply +allocates enough memory to hold the structure itself plus @code{N +- 1} operands which run ``off the end'' of the structure. For +example, to allocate space for a tuple with 3 operands, +@code{gimple_alloc} reserves @code{sizeof (struct +gimple_statement_with_ops) + 2 * sizeof (tree)} bytes. + +On the other hand, several fields in this tuple need to be shared +with the @code{gimple_statement_with_memory_ops} tuple. So, these +common fields are placed in @code{gimple_statement_with_ops_base} which +is then inherited from the other two tuples. + + +@multitable {@code{addresses_taken}} {56 + 8 * @code{num_ops} bytes} +@item @code{gsbase} @tab 256 +@item @code{addresses_taken} @tab 64 +@item @code{def_ops} @tab 64 +@item @code{use_ops} @tab 64 +@item @code{op} @tab @code{num_ops} * 64 +@item Total size @tab 56 + 8 * @code{num_ops} bytes +@end multitable + +@itemize @bullet +@item @code{gsbase} +Inherited from @code{struct gimple_statement_base}. + +@item @code{addresses_taken} +Bitmap holding the UIDs of all the @code{VAR_DECL}s whose addresses are +taken by this statement. For example, a statement of the form +@code{p = &b} will have the UID for symbol @code{b} in this set. + +@item @code{def_ops} +Array of pointers into the operand array indicating all the slots that +contain a variable written-to by the statement. This array is +also used for immediate use chaining. Note that it would be +possible to not rely on this array, but the changes required to +implement this are pretty invasive. + +@item @code{use_ops} +Similar to @code{def_ops} but for variables read by the statement. + +@item @code{op} +Array of trees with @code{num_ops} slots. +@end itemize + +@subsection @code{gimple_statement_with_memory_ops} + +This tuple is essentially identical to @code{gimple_statement_with_ops}, +except that it contains 4 additional fields to hold vectors +related memory stores and loads. Similar to the previous case, +the structure is split in two to accomodate for the operand +vector (@code{gimple_statement_with_memory_ops_base} and +@code{gimple_statement_with_memory_ops}). + + +@multitable {@code{addresses_taken}} {88 + 8 * @code{num_ops} bytes} +@item Field @tab Size (bits) +@item @code{gsbase} @tab 256 +@item @code{addresses_taken} @tab 64 +@item @code{def_ops} @tab 64 +@item @code{use_ops} @tab 64 +@item @code{vdef_ops} @tab 64 +@item @code{vuse_ops} @tab 64 +@item @code{stores} @tab 64 +@item @code{loads} @tab 64 +@item @code{op} @tab @code{num_ops} * 64 +@item Total size @tab 88 + 8 * @code{num_ops} bytes +@end multitable + +@itemize @bullet +@item @code{vdef_ops} +Similar to @code{def_ops} but for @code{VDEF} operators. There is +one entry per memory symbol written by this statement. This is +used to maintain the memory SSA use-def and def-def chains. + +@item @code{vuse_ops} +Similar to @code{use_ops} but for @code{VUSE} operators. There is +one entry per memory symbol loaded by this statement. This is +used to maintain the memory SSA use-def chains. + +@item @code{stores} +Bitset with all the UIDs for the symbols written-to by the +statement. This is different than @code{vdef_ops} in that all the +affected symbols are mentioned in this set. If memory +partitioning is enabled, the @code{vdef_ops} vector will refer to memory +partitions. Furthermore, no SSA information is stored in this +set. + +@item @code{loads} +Similar to @code{stores}, but for memory loads. (Note that there +is some amount of redundancy here, it should be possible to +reduce memory utilization further by removing these sets). +@end itemize + +All the other tuples are defined in terms of these three basic +ones. Each tuple will add some fields. The main gimple type +is defined to be the union of all these structures (@code{GTY} markers +elided for clarity): + +@smallexample +union gimple_statement_d +@{ + struct gimple_statement_base gsbase; + struct gimple_statement_with_ops gsops; + struct gimple_statement_with_memory_ops gsmem; + struct gimple_statement_omp omp; + struct gimple_statement_bind gimple_bind; + struct gimple_statement_catch gimple_catch; + struct gimple_statement_eh_filter gimple_eh_filter; + struct gimple_statement_phi gimple_phi; + struct gimple_statement_resx gimple_resx; + struct gimple_statement_try gimple_try; + struct gimple_statement_wce gimple_wce; + struct gimple_statement_asm gimple_asm; + struct gimple_statement_omp_critical gimple_omp_critical; + struct gimple_statement_omp_for gimple_omp_for; + struct gimple_statement_omp_parallel gimple_omp_parallel; + struct gimple_statement_omp_task gimple_omp_task; + struct gimple_statement_omp_sections gimple_omp_sections; + struct gimple_statement_omp_single gimple_omp_single; + struct gimple_statement_omp_continue gimple_omp_continue; + struct gimple_statement_omp_atomic_load gimple_omp_atomic_load; + struct gimple_statement_omp_atomic_store gimple_omp_atomic_store; +@}; +@end smallexample + + +@node GIMPLE instruction set +@section GIMPLE instruction set +@cindex GIMPLE instruction set + +The following table briefly describes the GIMPLE instruction set. + +@multitable {@code{GIMPLE_CHANGE_DYNAMIC_TYPE}} {High GIMPLE} {Low GIMPLE} +@item Instruction @tab High GIMPLE @tab Low GIMPLE +@item @code{GIMPLE_ASM} @tab x @tab x +@item @code{GIMPLE_ASSIGN} @tab x @tab x +@item @code{GIMPLE_BIND} @tab x @tab +@item @code{GIMPLE_CALL} @tab x @tab x +@item @code{GIMPLE_CATCH} @tab x @tab +@item @code{GIMPLE_CHANGE_DYNAMIC_TYPE} @tab x @tab x +@item @code{GIMPLE_COND} @tab x @tab x +@item @code{GIMPLE_EH_FILTER} @tab x @tab +@item @code{GIMPLE_GOTO} @tab x @tab x +@item @code{GIMPLE_LABEL} @tab x @tab x +@item @code{GIMPLE_NOP} @tab x @tab x +@item @code{GIMPLE_OMP_ATOMIC_LOAD} @tab x @tab x +@item @code{GIMPLE_OMP_ATOMIC_STORE} @tab x @tab x +@item @code{GIMPLE_OMP_CONTINUE} @tab x @tab x +@item @code{GIMPLE_OMP_CRITICAL} @tab x @tab x +@item @code{GIMPLE_OMP_FOR} @tab x @tab x +@item @code{GIMPLE_OMP_MASTER} @tab x @tab x +@item @code{GIMPLE_OMP_ORDERED} @tab x @tab x +@item @code{GIMPLE_OMP_PARALLEL} @tab x @tab x +@item @code{GIMPLE_OMP_RETURN} @tab x @tab x +@item @code{GIMPLE_OMP_SECTION} @tab x @tab x +@item @code{GIMPLE_OMP_SECTIONS} @tab x @tab x +@item @code{GIMPLE_OMP_SECTIONS_SWITCH} @tab x @tab x +@item @code{GIMPLE_OMP_SINGLE} @tab x @tab x +@item @code{GIMPLE_PHI} @tab @tab x +@item @code{GIMPLE_RESX} @tab @tab x +@item @code{GIMPLE_RETURN} @tab x @tab x +@item @code{GIMPLE_SWITCH} @tab x @tab x +@item @code{GIMPLE_TRY} @tab x @tab +@end multitable + +@node GIMPLE Exception Handling +@section Exception Handling +@cindex GIMPLE Exception Handling + +Other exception handling constructs are represented using +@code{GIMPLE_TRY_CATCH}. @code{GIMPLE_TRY_CATCH} has two operands. The +first operand is a sequence of statements to execute. If executing +these statements does not throw an exception, then the second operand +is ignored. Otherwise, if an exception is thrown, then the second +operand of the @code{GIMPLE_TRY_CATCH} is checked. The second +operand may have the following forms: + +@enumerate + +@item A sequence of statements to execute. When an exception occurs, +these statements are executed, and then the exception is rethrown. + +@item A sequence of @code{GIMPLE_CATCH} statements. Each +@code{GIMPLE_CATCH} has a list of applicable exception types and +handler code. If the thrown exception matches one of the caught +types, the associated handler code is executed. If the handler +code falls off the bottom, execution continues after the original +@code{GIMPLE_TRY_CATCH}. + +@item An @code{GIMPLE_EH_FILTER} statement. This has a list of +permitted exception types, and code to handle a match failure. If the +thrown exception does not match one of the allowed types, the +associated match failure code is executed. If the thrown exception +does match, it continues unwinding the stack looking for the next +handler. + +@end enumerate + +Currently throwing an exception is not directly represented in +GIMPLE, since it is implemented by calling a function. At some +point in the future we will want to add some way to express that +the call will throw an exception of a known type. + +Just before running the optimizers, the compiler lowers the +high-level EH constructs above into a set of @samp{goto}s, magic +labels, and EH regions. Continuing to unwind at the end of a +cleanup is represented with a @code{GIMPLE_RESX}. + + +@node Temporaries +@section Temporaries +@cindex Temporaries + +When gimplification encounters a subexpression that is too +complex, it creates a new temporary variable to hold the value of +the subexpression, and adds a new statement to initialize it +before the current statement. These special temporaries are known +as @samp{expression temporaries}, and are allocated using +@code{get_formal_tmp_var}. The compiler tries to always evaluate +identical expressions into the same temporary, to simplify +elimination of redundant calculations. + +We can only use expression temporaries when we know that it will +not be reevaluated before its value is used, and that it will not +be otherwise modified@footnote{These restrictions are derived +from those in Morgan 4.8.}. Other temporaries can be allocated +using @code{get_initialized_tmp_var} or @code{create_tmp_var}. + +Currently, an expression like @code{a = b + 5} is not reduced any +further. We tried converting it to something like +@smallexample + T1 = b + 5; + a = T1; +@end smallexample +but this bloated the representation for minimal benefit. However, a +variable which must live in memory cannot appear in an expression; its +value is explicitly loaded into a temporary first. Similarly, storing +the value of an expression to a memory variable goes through a +temporary. + +@node Operands +@section Operands +@cindex Operands + +In general, expressions in GIMPLE consist of an operation and the +appropriate number of simple operands; these operands must either be a +GIMPLE rvalue (@code{is_gimple_val}), i.e.@: a constant or a register +variable. More complex operands are factored out into temporaries, so +that +@smallexample + a = b + c + d +@end smallexample +becomes +@smallexample + T1 = b + c; + a = T1 + d; +@end smallexample + +The same rule holds for arguments to a @code{GIMPLE_CALL}. + +The target of an assignment is usually a variable, but can also be an +@code{INDIRECT_REF} or a compound lvalue as described below. + +@menu +* Compound Expressions:: +* Compound Lvalues:: +* Conditional Expressions:: +* Logical Operators:: +@end menu + +@node Compound Expressions +@subsection Compound Expressions +@cindex Compound Expressions + +The left-hand side of a C comma expression is simply moved into a separate +statement. + +@node Compound Lvalues +@subsection Compound Lvalues +@cindex Compound Lvalues + +Currently compound lvalues involving array and structure field references +are not broken down; an expression like @code{a.b[2] = 42} is not reduced +any further (though complex array subscripts are). This restriction is a +workaround for limitations in later optimizers; if we were to convert this +to + +@smallexample + T1 = &a.b; + T1[2] = 42; +@end smallexample + +alias analysis would not remember that the reference to @code{T1[2]} came +by way of @code{a.b}, so it would think that the assignment could alias +another member of @code{a}; this broke @code{struct-alias-1.c}. Future +optimizer improvements may make this limitation unnecessary. + +@node Conditional Expressions +@subsection Conditional Expressions +@cindex Conditional Expressions + +A C @code{?:} expression is converted into an @code{if} statement with +each branch assigning to the same temporary. So, + +@smallexample + a = b ? c : d; +@end smallexample +becomes +@smallexample + if (b == 1) + T1 = c; + else + T1 = d; + a = T1; +@end smallexample + +The GIMPLE level if-conversion pass re-introduces @code{?:} +expression, if appropriate. It is used to vectorize loops with +conditions using vector conditional operations. + +Note that in GIMPLE, @code{if} statements are represented using +@code{GIMPLE_COND}, as described below. + +@node Logical Operators +@subsection Logical Operators +@cindex Logical Operators + +Except when they appear in the condition operand of a +@code{GIMPLE_COND}, logical `and' and `or' operators are simplified +as follows: @code{a = b && c} becomes + +@smallexample + T1 = (bool)b; + if (T1 == true) + T1 = (bool)c; + a = T1; +@end smallexample + +Note that @code{T1} in this example cannot be an expression temporary, +because it has two different assignments. + +@subsection Manipulating operands + +All gimple operands are of type @code{tree}. But only certain +types of trees are allowed to be used as operand tuples. Basic +validation is controlled by the function +@code{get_gimple_rhs_class}, which given a tree code, returns an +@code{enum} with the following values of type @code{enum +gimple_rhs_class} + +@itemize @bullet +@item @code{GIMPLE_INVALID_RHS} +The tree cannot be used as a GIMPLE operand. + +@item @code{GIMPLE_BINARY_RHS} +The tree is a valid GIMPLE binary operation. + +@item @code{GIMPLE_UNARY_RHS} +The tree is a valid GIMPLE unary operation. + +@item @code{GIMPLE_SINGLE_RHS} +The tree is a single object, that cannot be split into simpler +operands (for instance, @code{SSA_NAME}, @code{VAR_DECL}, @code{COMPONENT_REF}, etc). + +This operand class also acts as an escape hatch for tree nodes +that may be flattened out into the operand vector, but would need +more than two slots on the RHS. For instance, a @code{COND_EXPR} +expression of the form @code{(a op b) ? x : y} could be flattened +out on the operand vector using 4 slots, but it would also +require additional processing to distinguish @code{c = a op b} +from @code{c = a op b ? x : y}. Something similar occurs with +@code{ASSERT_EXPR}. In time, these special case tree +expressions should be flattened into the operand vector. +@end itemize + +For tree nodes in the categories @code{GIMPLE_BINARY_RHS} and +@code{GIMPLE_UNARY_RHS}, they cannot be stored inside tuples directly. +They first need to be flattened and separated into individual +components. For instance, given the GENERIC expression + +@smallexample +a = b + c +@end smallexample + +its tree representation is: + +@smallexample +MODIFY_EXPR <VAR_DECL <a>, PLUS_EXPR <VAR_DECL <b>, VAR_DECL <c>>> +@end smallexample + +In this case, the GIMPLE form for this statement is logically +identical to its GENERIC form but in GIMPLE, the @code{PLUS_EXPR} +on the RHS of the assignment is not represented as a tree, +instead the two operands are taken out of the @code{PLUS_EXPR} sub-tree +and flattened into the GIMPLE tuple as follows: + +@smallexample +GIMPLE_ASSIGN <PLUS_EXPR, VAR_DECL <a>, VAR_DECL <b>, VAR_DECL <c>> +@end smallexample + +@subsection Operand vector allocation + +The operand vector is stored at the bottom of the three tuple +structures that accept operands. This means, that depending on +the code of a given statement, its operand vector will be at +different offsets from the base of the structure. To access +tuple operands use the following accessors + +@deftypefn {GIMPLE function} unsigned gimple_num_ops (gimple g) +Returns the number of operands in statement G. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_op (gimple g, unsigned i) +Returns operand @code{I} from statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree *gimple_ops (gimple g) +Returns a pointer into the operand vector for statement @code{G}. This +is computed using an internal table called @code{gimple_ops_offset_}[]. +This table is indexed by the gimple code of @code{G}. + +When the compiler is built, this table is filled-in using the +sizes of the structures used by each statement code defined in +gimple.def. Since the operand vector is at the bottom of the +structure, for a gimple code @code{C} the offset is computed as sizeof +(struct-of @code{C}) - sizeof (tree). + +This mechanism adds one memory indirection to every access when +using @code{gimple_op}(), if this becomes a bottleneck, a pass can +choose to memoize the result from @code{gimple_ops}() and use that to +access the operands. +@end deftypefn + +@subsection Operand validation + +When adding a new operand to a gimple statement, the operand will +be validated according to what each tuple accepts in its operand +vector. These predicates are called by the +@code{gimple_<name>_set_...()}. Each tuple will use one of the +following predicates (Note, this list is not exhaustive): + +@deftypefn {GIMPLE function} is_gimple_operand (tree t) +This is the most permissive of the predicates. It essentially +checks whether t has a @code{gimple_rhs_class} of @code{GIMPLE_SINGLE_RHS}. +@end deftypefn + + +@deftypefn {GIMPLE function} is_gimple_val (tree t) +Returns true if t is a "GIMPLE value", which are all the +non-addressable stack variables (variables for which +@code{is_gimple_reg} returns true) and constants (expressions for which +@code{is_gimple_min_invariant} returns true). +@end deftypefn + +@deftypefn {GIMPLE function} is_gimple_addressable (tree t) +Returns true if t is a symbol or memory reference whose address +can be taken. +@end deftypefn + +@deftypefn {GIMPLE function} is_gimple_asm_val (tree t) +Similar to @code{is_gimple_val} but it also accepts hard registers. +@end deftypefn + +@deftypefn {GIMPLE function} is_gimple_call_addr (tree t) +Return true if t is a valid expression to use as the function +called by a @code{GIMPLE_CALL}. +@end deftypefn + +@deftypefn {GIMPLE function} is_gimple_constant (tree t) +Return true if t is a valid gimple constant. +@end deftypefn + +@deftypefn {GIMPLE function} is_gimple_min_invariant (tree t) +Return true if t is a valid minimal invariant. This is different +from constants, in that the specific value of t may not be known +at compile time, but it is known that it doesn't change (e.g., +the address of a function local variable). +@end deftypefn + +@deftypefn {GIMPLE function} is_gimple_min_invariant_address (tree t) +Return true if t is an @code{ADDR_EXPR} that does not change once the +program is running. +@end deftypefn + + +@subsection Statement validation + +@deftypefn {GIMPLE function} is_gimple_assign (gimple g) +Return true if the code of g is @code{GIMPLE_ASSIGN}. +@end deftypefn + +@deftypefn {GIMPLE function} is_gimple_call (gimple g) +Return true if the code of g is @code{GIMPLE_CALL} +@end deftypefn + +@deftypefn {GIMPLE function} gimple_assign_cast_p (gimple g) +Return true if g is a @code{GIMPLE_ASSIGN} that performs a type cast +operation +@end deftypefn + +@node Manipulating GIMPLE statements +@section Manipulating GIMPLE statements +@cindex Manipulating GIMPLE statements + +This section documents all the functions available to handle each +of the GIMPLE instructions. + +@subsection Common accessors +The following are common accessors for gimple statements. + +@deftypefn {GIMPLE function} enum gimple_code gimple_code (gimple g) +Return the code for statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} basic_block gimple_bb (gimple g) +Return the basic block to which statement @code{G} belongs to. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_block (gimple g) +Return the lexical scope block holding statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_expr_type (gimple stmt) +Return the type of the main expression computed by @code{STMT}. Return +@code{void_type_node} if @code{STMT} computes nothing. This will only return +something meaningful for @code{GIMPLE_ASSIGN}, @code{GIMPLE_COND} and +@code{GIMPLE_CALL}. For all other tuple codes, it will return +@code{void_type_node}. +@end deftypefn + +@deftypefn {GIMPLE function} enum tree_code gimple_expr_code (gimple stmt) +Return the tree code for the expression computed by @code{STMT}. This +is only meaningful for @code{GIMPLE_CALL}, @code{GIMPLE_ASSIGN} and +@code{GIMPLE_COND}. If @code{STMT} is @code{GIMPLE_CALL}, it will return @code{CALL_EXPR}. +For @code{GIMPLE_COND}, it returns the code of the comparison predicate. +For @code{GIMPLE_ASSIGN} it returns the code of the operation performed +by the @code{RHS} of the assignment. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_set_block (gimple g, tree block) +Set the lexical scope block of @code{G} to @code{BLOCK}. +@end deftypefn + +@deftypefn {GIMPLE function} location_t gimple_locus (gimple g) +Return locus information for statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_set_locus (gimple g, location_t locus) +Set locus information for statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} bool gimple_locus_empty_p (gimple g) +Return true if @code{G} does not have locus information. +@end deftypefn + +@deftypefn {GIMPLE function} bool gimple_no_warning_p (gimple stmt) +Return true if no warnings should be emitted for statement @code{STMT}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_set_visited (gimple stmt, bool visited_p) +Set the visited status on statement @code{STMT} to @code{VISITED_P}. +@end deftypefn + +@deftypefn {GIMPLE function} bool gimple_visited_p (gimple stmt) +Return the visited status on statement @code{STMT}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_set_plf (gimple stmt, enum plf_mask plf, bool val_p) +Set pass local flag @code{PLF} on statement @code{STMT} to @code{VAL_P}. +@end deftypefn + +@deftypefn {GIMPLE function} unsigned int gimple_plf (gimple stmt, enum plf_mask plf) +Return the value of pass local flag @code{PLF} on statement @code{STMT}. +@end deftypefn + +@deftypefn {GIMPLE function} bool gimple_has_ops (gimple g) +Return true if statement @code{G} has register or memory operands. +@end deftypefn + +@deftypefn {GIMPLE function} bool gimple_has_mem_ops (gimple g) +Return true if statement @code{G} has memory operands. +@end deftypefn + +@deftypefn {GIMPLE function} unsigned gimple_num_ops (gimple g) +Return the number of operands for statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree *gimple_ops (gimple g) +Return the array of operands for statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_op (gimple g, unsigned i) +Return operand @code{I} for statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree *gimple_op_ptr (gimple g, unsigned i) +Return a pointer to operand @code{I} for statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_set_op (gimple g, unsigned i, tree op) +Set operand @code{I} of statement @code{G} to @code{OP}. +@end deftypefn + +@deftypefn {GIMPLE function} bitmap gimple_addresses_taken (gimple stmt) +Return the set of symbols that have had their address taken by +@code{STMT}. +@end deftypefn + +@deftypefn {GIMPLE function} struct def_optype_d *gimple_def_ops (gimple g) +Return the set of @code{DEF} operands for statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_set_def_ops (gimple g, struct def_optype_d *def) +Set @code{DEF} to be the set of @code{DEF} operands for statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} struct use_optype_d *gimple_use_ops (gimple g) +Return the set of @code{USE} operands for statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_set_use_ops (gimple g, struct use_optype_d *use) +Set @code{USE} to be the set of @code{USE} operands for statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} struct voptype_d *gimple_vuse_ops (gimple g) +Return the set of @code{VUSE} operands for statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_set_vuse_ops (gimple g, struct voptype_d *ops) +Set @code{OPS} to be the set of @code{VUSE} operands for statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} struct voptype_d *gimple_vdef_ops (gimple g) +Return the set of @code{VDEF} operands for statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_set_vdef_ops (gimple g, struct voptype_d *ops) +Set @code{OPS} to be the set of @code{VDEF} operands for statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} bitmap gimple_loaded_syms (gimple g) +Return the set of symbols loaded by statement @code{G}. Each element of +the set is the @code{DECL_UID} of the corresponding symbol. +@end deftypefn + +@deftypefn {GIMPLE function} bitmap gimple_stored_syms (gimple g) +Return the set of symbols stored by statement @code{G}. Each element of +the set is the @code{DECL_UID} of the corresponding symbol. +@end deftypefn + +@deftypefn {GIMPLE function} bool gimple_modified_p (gimple g) +Return true if statement @code{G} has operands and the modified field +has been set. +@end deftypefn + +@deftypefn {GIMPLE function} bool gimple_has_volatile_ops (gimple stmt) +Return true if statement @code{STMT} contains volatile operands. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_set_has_volatile_ops (gimple stmt, bool volatilep) +Return true if statement @code{STMT} contains volatile operands. +@end deftypefn + +@deftypefn {GIMPLE function} void update_stmt (gimple s) +Mark statement @code{S} as modified, and update it. +@end deftypefn + +@deftypefn {GIMPLE function} void update_stmt_if_modified (gimple s) +Update statement @code{S} if it has been marked modified. +@end deftypefn + +@deftypefn {GIMPLE function} gimple gimple_copy (gimple stmt) +Return a deep copy of statement @code{STMT}. +@end deftypefn + +@deftypefn {GIMPLE function} gimple gimple_copy_call_skip_args (gimple stmt, bitmap args_to_skip) +Build a @code{GIMPLE_CALL} identical to @code{STMT} but skipping the arguments +in the positions marked by the set @code{ARGS_TO_SKIP}. +@end deftypefn + +@node Tuple specific accessors +@section Tuple specific accessors +@cindex Tuple specific accessors + +@menu +* @code{GIMPLE_ASM}:: +* @code{GIMPLE_ASSIGN}:: +* @code{GIMPLE_BIND}:: +* @code{GIMPLE_CALL}:: +* @code{GIMPLE_CATCH}:: +* @code{GIMPLE_CHANGE_DYNAMIC_TYPE}:: +* @code{GIMPLE_COND}:: +* @code{GIMPLE_EH_FILTER}:: +* @code{GIMPLE_LABEL}:: +* @code{GIMPLE_NOP}:: +* @code{GIMPLE_OMP_ATOMIC_LOAD}:: +* @code{GIMPLE_OMP_ATOMIC_STORE}:: +* @code{GIMPLE_OMP_CONTINUE}:: +* @code{GIMPLE_OMP_CRITICAL}:: +* @code{GIMPLE_OMP_FOR}:: +* @code{GIMPLE_OMP_MASTER}:: +* @code{GIMPLE_OMP_ORDERED}:: +* @code{GIMPLE_OMP_PARALLEL}:: +* @code{GIMPLE_OMP_RETURN}:: +* @code{GIMPLE_OMP_SECTION}:: +* @code{GIMPLE_OMP_SECTIONS}:: +* @code{GIMPLE_OMP_SINGLE}:: +* @code{GIMPLE_PHI}:: +* @code{GIMPLE_RESX}:: +* @code{GIMPLE_RETURN}:: +* @code{GIMPLE_SWITCH}:: +* @code{GIMPLE_TRY}:: +* @code{GIMPLE_WITH_CLEANUP_EXPR}:: +@end menu + + +@node @code{GIMPLE_ASM} +@subsection @code{GIMPLE_ASM} +@cindex @code{GIMPLE_ASM} + +@deftypefn {GIMPLE function} gimple gimple_build_asm (const char *string, ninputs, noutputs, nclobbers, ...) +Build a @code{GIMPLE_ASM} statement. This statement is used for +building in-line assembly constructs. @code{STRING} is the assembly +code. @code{NINPUT} is the number of register inputs. @code{NOUTPUT} is the +number of register outputs. @code{NCLOBBERS} is the number of clobbered +registers. The rest of the arguments trees for each input, +output, and clobbered registers. +@end deftypefn + +@deftypefn {GIMPLE function} gimple gimple_build_asm_vec (const char *, VEC(tree,gc) *, VEC(tree,gc) *, VEC(tree,gc) *) +Identical to gimple_build_asm, but the arguments are passed in +VECs. +@end deftypefn + +@deftypefn {GIMPLE function} gimple_asm_ninputs (gimple g) +Return the number of input operands for @code{GIMPLE_ASM} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} gimple_asm_noutputs (gimple g) +Return the number of output operands for @code{GIMPLE_ASM} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} gimple_asm_nclobbers (gimple g) +Return the number of clobber operands for @code{GIMPLE_ASM} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_asm_input_op (gimple g, unsigned index) +Return input operand @code{INDEX} of @code{GIMPLE_ASM} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_asm_set_input_op (gimple g, unsigned index, tree in_op) +Set @code{IN_OP} to be input operand @code{INDEX} in @code{GIMPLE_ASM} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_asm_output_op (gimple g, unsigned index) +Return output operand @code{INDEX} of @code{GIMPLE_ASM} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_asm_set_output_op (gimple g, unsigne +index, tree out_op) +Set @code{OUT_OP} to be output operand @code{INDEX} in @code{GIMPLE_ASM} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_asm_clobber_op (gimple g, unsigned index) +Return clobber operand @code{INDEX} of @code{GIMPLE_ASM} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_asm_set_clobber_op (gimple g, unsigned index, tree clobber_op) +Set @code{CLOBBER_OP} to be clobber operand @code{INDEX} in @code{GIMPLE_ASM} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} const char *gimple_asm_string (gimple g) +Return the string representing the assembly instruction in +@code{GIMPLE_ASM} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} bool gimple_asm_volatile_p (gimple g) +Return true if @code{G} is an asm statement marked volatile. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_asm_set_volatile (gimple g) +Mark asm statement @code{G} as volatile. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_asm_clear_volatile (gimple g) +Remove volatile marker from asm statement @code{G}. +@end deftypefn + +@node @code{GIMPLE_ASSIGN} +@subsection @code{GIMPLE_ASSIGN} +@cindex @code{GIMPLE_ASSIGN} + +@deftypefn {GIMPLE function} gimple gimple_build_assign (tree lhs, tree rhs) +Build a @code{GIMPLE_ASSIGN} statement. The left-hand side is an lvalue +passed in lhs. The right-hand side can be either a unary or +binary tree expression. The expression tree rhs will be +flattened and its operands assigned to the corresponding operand +slots in the new statement. This function is useful when you +already have a tree expression that you want to convert into a +tuple. However, try to avoid building expression trees for the +sole purpose of calling this function. If you already have the +operands in separate trees, it is better to use +@code{gimple_build_assign_with_ops}. +@end deftypefn + + +@deftypefn {GIMPLE function} gimple gimplify_assign (tree dst, tree src, gimple_seq *seq_p) +Build a new @code{GIMPLE_ASSIGN} tuple and append it to the end of +@code{*SEQ_P}. +@end deftypefn + +@code{DST}/@code{SRC} are the destination and source respectively. You can +pass ungimplified trees in @code{DST} or @code{SRC}, in which +case they will be converted to a gimple operand if necessary. + +This function returns the newly created @code{GIMPLE_ASSIGN} tuple. + +@deftypefn {GIMPLE function} gimple gimple_build_assign_with_ops (enum tree_code subcode, tree lhs, tree op1, tree op2) +This function is similar to @code{gimple_build_assign}, but is used to +build a @code{GIMPLE_ASSIGN} statement when the operands of the +right-hand side of the assignment are already split into +different operands. + +The left-hand side is an lvalue passed in lhs. Subcode is the +@code{tree_code} for the right-hand side of the assignment. Op1 and op2 +are the operands. If op2 is null, subcode must be a @code{tree_code} +for a unary expression. +@end deftypefn + +@deftypefn {GIMPLE function} enum tree_code gimple_assign_rhs_code (gimple g) +Return the code of the expression computed on the @code{RHS} of +assignment statement @code{G}. +@end deftypefn + + +@deftypefn {GIMPLE function} enum gimple_rhs_class gimple_assign_rhs_class (gimple g) +Return the gimple rhs class of the code fo the expression +computed on the rhs of assignment statment @code{G}. This will never +return @code{GIMPLE_INVALID_RHS}. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_assign_lhs (gimple g) +Return the @code{LHS} of assignment statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree *gimple_assign_lhs_ptr (gimple g) +Return a pointer to the @code{LHS} of assignment statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_assign_rhs1 (gimple g) +Return the first operand on the @code{RHS} of assignment statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree *gimple_assign_rhs1_ptr (gimple g) +Return the address of the first operand on the @code{RHS} of assignment +statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_assign_rhs2 (gimple g) +Return the second operand on the @code{RHS} of assignment statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree *gimple_assign_rhs2_ptr (gimple g) +Return the address of the second operand on the @code{RHS} of assignment +statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_assign_set_lhs (gimple g, tree lhs) +Set @code{LHS} to be the @code{LHS} operand of assignment statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_assign_set_rhs1 (gimple g, tree rhs) +Set @code{RHS} to be the first operand on the @code{RHS} of assignment +statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_assign_rhs2 (gimple g) +Return the second operand on the @code{RHS} of assignment statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree *gimple_assign_rhs2_ptr (gimple g) +Return a pointer to the second operand on the @code{RHS} of assignment +statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_assign_set_rhs2 (gimple g, tree rhs) +Set @code{RHS} to be the second operand on the @code{RHS} of assignment +statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} bool gimple_assign_cast_p (gimple s) +Return true if @code{S} is an type-cast assignment. +@end deftypefn + + +@node @code{GIMPLE_BIND} +@subsection @code{GIMPLE_BIND} +@cindex @code{GIMPLE_BIND} + +@deftypefn {GIMPLE function} gimple gimple_build_bind (tree vars, gimple_seq body) +Build a @code{GIMPLE_BIND} statement with a list of variables in @code{VARS} +and a body of statements in sequence @code{BODY}. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_bind_vars (gimple g) +Return the variables declared in the @code{GIMPLE_BIND} statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_bind_set_vars (gimple g, tree vars) +Set @code{VARS} to be the set of variables declared in the @code{GIMPLE_BIND} +statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_bind_append_vars (gimple g, tree vars) +Append @code{VARS} to the set of variables declared in the @code{GIMPLE_BIND} +statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} gimple_seq gimple_bind_body (gimple g) +Return the GIMPLE sequence contained in the @code{GIMPLE_BIND} statement +@code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_bind_set_body (gimple g, gimple_seq seq) +Set @code{SEQ} to be sequence contained in the @code{GIMPLE_BIND} statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_bind_add_stmt (gimple gs, gimple stmt) +Append a statement to the end of a @code{GIMPLE_BIND}'s body. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_bind_add_seq (gimple gs, gimple_seq seq) +Append a sequence of statements to the end of a @code{GIMPLE_BIND}'s +body. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_bind_block (gimple g) +Return the @code{TREE_BLOCK} node associated with @code{GIMPLE_BIND} statement +@code{G}. This is analogous to the @code{BIND_EXPR_BLOCK} field in trees. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_bind_set_block (gimple g, tree block) +Set @code{BLOCK} to be the @code{TREE_BLOCK} node associated with @code{GIMPLE_BIND} +statement @code{G}. +@end deftypefn + + +@node @code{GIMPLE_CALL} +@subsection @code{GIMPLE_CALL} +@cindex @code{GIMPLE_CALL} + +@deftypefn {GIMPLE function} gimple gimple_build_call (tree fn, unsigned nargs, ...) +Build a @code{GIMPLE_CALL} statement to function @code{FN}. The argument @code{FN} +must be either a @code{FUNCTION_DECL} or a gimple call address as +determined by @code{is_gimple_call_addr}. @code{NARGS} are the number of +arguments. The rest of the arguments follow the argument @code{NARGS}, +and must be trees that are valid as rvalues in gimple (i.e., each +operand is validated with @code{is_gimple_operand}). +@end deftypefn + + +@deftypefn {GIMPLE function} gimple gimple_build_call_from_tree (tree call_expr) +Build a @code{GIMPLE_CALL} from a @code{CALL_EXPR} node. The arguments and the +function are taken from the expression directly. This routine +assumes that @code{call_expr} is already in GIMPLE form. That is, its +operands are GIMPLE values and the function call needs no further +simplification. All the call flags in @code{call_expr} are copied over +to the new @code{GIMPLE_CALL}. +@end deftypefn + +@deftypefn {GIMPLE function} gimple gimple_build_call_vec (tree fn, @code{VEC}(tree, heap) *args) +Identical to @code{gimple_build_call} but the arguments are stored in a +@code{VEC}(). +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_call_lhs (gimple g) +Return the @code{LHS} of call statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree *gimple_call_lhs_ptr (gimple g) +Return a pointer to the @code{LHS} of call statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_call_set_lhs (gimple g, tree lhs) +Set @code{LHS} to be the @code{LHS} operand of call statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_call_fn (gimple g) +Return the tree node representing the function called by call +statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_call_set_fn (gimple g, tree fn) +Set @code{FN} to be the function called by call statement @code{G}. This has +to be a gimple value specifying the address of the called +function. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_call_fndecl (gimple g) +If a given @code{GIMPLE_CALL}'s callee is a @code{FUNCTION_DECL}, return it. +Otherwise return @code{NULL}. This function is analogous to +@code{get_callee_fndecl} in @code{GENERIC}. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_call_set_fndecl (gimple g, tree fndecl) +Set the called function to @code{FNDECL}. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_call_return_type (gimple g) +Return the type returned by call statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_call_chain (gimple g) +Return the static chain for call statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_call_set_chain (gimple g, tree chain) +Set @code{CHAIN} to be the static chain for call statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} gimple_call_num_args (gimple g) +Return the number of arguments used by call statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_call_arg (gimple g, unsigned index) +Return the argument at position @code{INDEX} for call statement @code{G}. The +first argument is 0. +@end deftypefn + +@deftypefn {GIMPLE function} tree *gimple_call_arg_ptr (gimple g, unsigned index) +Return a pointer to the argument at position @code{INDEX} for call +statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_call_set_arg (gimple g, unsigned index, tree arg) +Set @code{ARG} to be the argument at position @code{INDEX} for call statement +@code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_call_set_tail (gimple s) +Mark call statement @code{S} as being a tail call (i.e., a call just +before the exit of a function). These calls are candidate for +tail call optimization. +@end deftypefn + +@deftypefn {GIMPLE function} bool gimple_call_tail_p (gimple s) +Return true if @code{GIMPLE_CALL} @code{S} is marked as a tail call. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_call_mark_uninlinable (gimple s) +Mark @code{GIMPLE_CALL} @code{S} as being uninlinable. +@end deftypefn + +@deftypefn {GIMPLE function} bool gimple_call_cannot_inline_p (gimple s) +Return true if @code{GIMPLE_CALL} @code{S} cannot be inlined. +@end deftypefn + +@deftypefn {GIMPLE function} bool gimple_call_noreturn_p (gimple s) +Return true if @code{S} is a noreturn call. +@end deftypefn + + +@node @code{GIMPLE_CATCH} +@subsection @code{GIMPLE_CATCH} +@cindex @code{GIMPLE_CATCH} + +@deftypefn {GIMPLE function} gimple gimple_build_catch (tree types, gimple_seq handler) +Build a @code{GIMPLE_CATCH} statement. @code{TYPES} are the tree types this +catch handles. @code{HANDLER} is a sequence of statements with the code +for the handler. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_catch_types (gimple g) +Return the types handled by @code{GIMPLE_CATCH} statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree *gimple_catch_types_ptr (gimple g) +Return a pointer to the types handled by @code{GIMPLE_CATCH} statement +@code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} gimple_seq gimple_catch_handler (gimple g) +Return the GIMPLE sequence representing the body of the handler +of @code{GIMPLE_CATCH} statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_catch_set_types (gimple g, tree t) +Set @code{T} to be the set of types handled by @code{GIMPLE_CATCH} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_catch_set_handler (gimple g, gimple_seq handler) +Set @code{HANDLER} to be the body of @code{GIMPLE_CATCH} @code{G}. +@end deftypefn + +@node @code{GIMPLE_CHANGE_DYNAMIC_TYPE} +@subsection @code{GIMPLE_CHANGE_DYNAMIC_TYPE} +@cindex @code{GIMPLE_CHANGE_DYNAMIC_TYPE} + +@deftypefn {GIMPLE function} gimple gimple_build_cdt (tree type, tree ptr) +Build a @code{GIMPLE_CHANGE_DYNAMIC_TYPE} statement. @code{TYPE} is the new +type for the location @code{PTR}. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_cdt_new_type (gimple g) +Return the new type set by @code{GIMPLE_CHANGE_DYNAMIC_TYPE} statement +@code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree *gimple_cdt_new_type_ptr (gimple g) +Return a pointer to the new type set by +@code{GIMPLE_CHANGE_DYNAMIC_TYPE} statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_cdt_set_new_type (gimple g, tree new_type) +Set @code{NEW_TYPE} to be the type returned by +@code{GIMPLE_CHANGE_DYNAMIC_TYPE} statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_cdt_location (gimple g) +Return the location affected by @code{GIMPLE_CHANGE_DYNAMIC_TYPE} +statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree *gimple_cdt_location_ptr (gimple g) +Return a pointer to the location affected by +@code{GIMPLE_CHANGE_DYNAMIC_TYPE} statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_cdt_set_location (gimple g, tree ptr) +Set @code{PTR} to be the location affected by @code{GIMPLE_CHANGE_DYNAMIC_TYPE} +statement @code{G}. +@end deftypefn + + +@node @code{GIMPLE_COND} +@subsection @code{GIMPLE_COND} +@cindex @code{GIMPLE_COND} + +@deftypefn {GIMPLE function} gimple gimple_build_cond (enum tree_code pred_code, tree lhs, tree rhs, tree t_label, tree f_label) +Build a @code{GIMPLE_COND} statement. @code{A} @code{GIMPLE_COND} statement compares +@code{LHS} and @code{RHS} and if the condition in @code{PRED_CODE} is true, jump to +the label in @code{t_label}, otherwise jump to the label in @code{f_label}. +@code{PRED_CODE} are relational operator tree codes like @code{EQ_EXPR}, +@code{LT_EXPR}, @code{LE_EXPR}, @code{NE_EXPR}, etc. +@end deftypefn + + +@deftypefn {GIMPLE function} gimple gimple_build_cond_from_tree (tree cond, tree t_label, tree f_label) +Build a @code{GIMPLE_COND} statement from the conditional expression +tree @code{COND}. @code{T_LABEL} and @code{F_LABEL} are as in @code{gimple_build_cond}. +@end deftypefn + +@deftypefn {GIMPLE function} enum tree_code gimple_cond_code (gimple g) +Return the code of the predicate computed by conditional +statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_cond_set_code (gimple g, enum tree_code code) +Set @code{CODE} to be the predicate code for the conditional statement +@code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_cond_lhs (gimple g) +Return the @code{LHS} of the predicate computed by conditional statement +@code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_cond_set_lhs (gimple g, tree lhs) +Set @code{LHS} to be the @code{LHS} operand of the predicate computed by +conditional statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_cond_rhs (gimple g) +Return the @code{RHS} operand of the predicate computed by conditional +@code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_cond_set_rhs (gimple g, tree rhs) +Set @code{RHS} to be the @code{RHS} operand of the predicate computed by +conditional statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_cond_true_label (gimple g) +Return the label used by conditional statement @code{G} when its +predicate evaluates to true. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_cond_set_true_label (gimple g, tree label) +Set @code{LABEL} to be the label used by conditional statement @code{G} when +its predicate evaluates to true. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_cond_set_false_label (gimple g, tree label) +Set @code{LABEL} to be the label used by conditional statement @code{G} when +its predicate evaluates to false. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_cond_false_label (gimple g) +Return the label used by conditional statement @code{G} when its +predicate evaluates to false. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_cond_make_false (gimple g) +Set the conditional @code{COND_STMT} to be of the form 'if (1 == 0)'. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_cond_make_true (gimple g) +Set the conditional @code{COND_STMT} to be of the form 'if (1 == 1)'. +@end deftypefn + +@node @code{GIMPLE_EH_FILTER} +@subsection @code{GIMPLE_EH_FILTER} +@cindex @code{GIMPLE_EH_FILTER} + +@deftypefn {GIMPLE function} gimple gimple_build_eh_filter (tree types, gimple_seq failure) +Build a @code{GIMPLE_EH_FILTER} statement. @code{TYPES} are the filter's +types. @code{FAILURE} is a sequence with the filter's failure action. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_eh_filter_types (gimple g) +Return the types handled by @code{GIMPLE_EH_FILTER} statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree *gimple_eh_filter_types_ptr (gimple g) +Return a pointer to the types handled by @code{GIMPLE_EH_FILTER} +statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} gimple_seq gimple_eh_filter_failure (gimple g) +Return the sequence of statement to execute when @code{GIMPLE_EH_FILTER} +statement fails. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_eh_filter_set_types (gimple g, tree types) +Set @code{TYPES} to be the set of types handled by @code{GIMPLE_EH_FILTER} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_eh_filter_set_failure (gimple g, gimple_seq failure) +Set @code{FAILURE} to be the sequence of statements to execute on +failure for @code{GIMPLE_EH_FILTER} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} bool gimple_eh_filter_must_not_throw (gimple g) +Return the @code{EH_FILTER_MUST_NOT_THROW} flag. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_eh_filter_set_must_not_throw (gimple g, bool mntp) +Set the @code{EH_FILTER_MUST_NOT_THROW} flag. +@end deftypefn + + +@node @code{GIMPLE_LABEL} +@subsection @code{GIMPLE_LABEL} +@cindex @code{GIMPLE_LABEL} + +@deftypefn {GIMPLE function} gimple gimple_build_label (tree label) +Build a @code{GIMPLE_LABEL} statement with corresponding to the tree +label, @code{LABEL}. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_label_label (gimple g) +Return the @code{LABEL_DECL} node used by @code{GIMPLE_LABEL} statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_label_set_label (gimple g, tree label) +Set @code{LABEL} to be the @code{LABEL_DECL} node used by @code{GIMPLE_LABEL} +statement @code{G}. +@end deftypefn + + +@deftypefn {GIMPLE function} gimple gimple_build_goto (tree dest) +Build a @code{GIMPLE_GOTO} statement to label @code{DEST}. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_goto_dest (gimple g) +Return the destination of the unconditional jump @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_goto_set_dest (gimple g, tree dest) +Set @code{DEST} to be the destination of the unconditonal jump @code{G}. +@end deftypefn + + +@node @code{GIMPLE_NOP} +@subsection @code{GIMPLE_NOP} +@cindex @code{GIMPLE_NOP} + +@deftypefn {GIMPLE function} gimple gimple_build_nop (void) +Build a @code{GIMPLE_NOP} statement. +@end deftypefn + +@deftypefn {GIMPLE function} bool gimple_nop_p (gimple g) +Returns @code{TRUE} if statement @code{G} is a @code{GIMPLE_NOP}. +@end deftypefn + +@node @code{GIMPLE_OMP_ATOMIC_LOAD} +@subsection @code{GIMPLE_OMP_ATOMIC_LOAD} +@cindex @code{GIMPLE_OMP_ATOMIC_LOAD} + +@deftypefn {GIMPLE function} gimple gimple_build_omp_atomic_load (tree lhs, tree rhs) +Build a @code{GIMPLE_OMP_ATOMIC_LOAD} statement. @code{LHS} is the left-hand +side of the assignment. @code{RHS} is the right-hand side of the +assignment. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_omp_atomic_load_set_lhs (gimple g, tree lhs) +Set the @code{LHS} of an atomic load. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_omp_atomic_load_lhs (gimple g) +Get the @code{LHS} of an atomic load. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_omp_atomic_load_set_rhs (gimple g, tree rhs) +Set the @code{RHS} of an atomic set. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_omp_atomic_load_rhs (gimple g) +Get the @code{RHS} of an atomic set. +@end deftypefn + + +@node @code{GIMPLE_OMP_ATOMIC_STORE} +@subsection @code{GIMPLE_OMP_ATOMIC_STORE} +@cindex @code{GIMPLE_OMP_ATOMIC_STORE} + +@deftypefn {GIMPLE function} gimple gimple_build_omp_atomic_store (tree val) +Build a @code{GIMPLE_OMP_ATOMIC_STORE} statement. @code{VAL} is the value to be +stored. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_omp_atomic_store_set_val (gimple g, tree val) +Set the value being stored in an atomic store. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_omp_atomic_store_val (gimple g) +Return the value being stored in an atomic store. +@end deftypefn + +@node @code{GIMPLE_OMP_CONTINUE} +@subsection @code{GIMPLE_OMP_CONTINUE} +@cindex @code{GIMPLE_OMP_CONTINUE} + +@deftypefn {GIMPLE function} gimple gimple_build_omp_continue (tree control_def, tree control_use) +Build a @code{GIMPLE_OMP_CONTINUE} statement. @code{CONTROL_DEF} is the +definition of the control variable. @code{CONTROL_USE} is the use of +the control variable. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_omp_continue_control_def (gimple s) +Return the definition of the control variable on a +@code{GIMPLE_OMP_CONTINUE} in @code{S}. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_omp_continue_control_def_ptr (gimple s) +Same as above, but return the pointer. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_omp_continue_set_control_def (gimple s) +Set the control variable definition for a @code{GIMPLE_OMP_CONTINUE} +statement in @code{S}. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_omp_continue_control_use (gimple s) +Return the use of the control variable on a @code{GIMPLE_OMP_CONTINUE} +in @code{S}. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_omp_continue_control_use_ptr (gimple s) +Same as above, but return the pointer. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_omp_continue_set_control_use (gimple s) +Set the control variable use for a @code{GIMPLE_OMP_CONTINUE} statement +in @code{S}. +@end deftypefn + + +@node @code{GIMPLE_OMP_CRITICAL} +@subsection @code{GIMPLE_OMP_CRITICAL} +@cindex @code{GIMPLE_OMP_CRITICAL} + +@deftypefn {GIMPLE function} gimple gimple_build_omp_critical (gimple_seq body, tree name) +Build a @code{GIMPLE_OMP_CRITICAL} statement. @code{BODY} is the sequence of +statements for which only one thread can execute. @code{NAME} is an +optional identifier for this critical block. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_omp_critical_name (gimple g) +Return the name associated with @code{OMP_CRITICAL} statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree *gimple_omp_critical_name_ptr (gimple g) +Return a pointer to the name associated with @code{OMP} critical +statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_omp_critical_set_name (gimple g, tree name) +Set @code{NAME} to be the name associated with @code{OMP} critical statement @code{G}. +@end deftypefn + +@node @code{GIMPLE_OMP_FOR} +@subsection @code{GIMPLE_OMP_FOR} +@cindex @code{GIMPLE_OMP_FOR} + +@deftypefn {GIMPLE function} gimple gimple_build_omp_for (gimple_seq body, tre +clauses, tree index, tree initial, tree final, tree incr, +gimple_seq pre_body, enum tree_code omp_for_cond) +Build a @code{GIMPLE_OMP_FOR} statement. @code{BODY} is sequence of statements +inside the for loop. @code{CLAUSES}, are any of the @code{OMP} loop +construct's clauses: private, firstprivate, lastprivate, +reductions, ordered, schedule, and nowait. @code{PRE_BODY} is the +sequence of statements that are loop invariant. @code{INDEX} is the +index variable. @code{INITIAL} is the initial value of @code{INDEX}. @code{FINAL} is +final value of @code{INDEX}. OMP_FOR_COND is the predicate used to +compare @code{INDEX} and @code{FINAL}. @code{INCR} is the increment expression. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_omp_for_clauses (gimple g) +Return the clauses associated with @code{OMP_FOR} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree *gimple_omp_for_clauses_ptr (gimple g) +Return a pointer to the @code{OMP_FOR} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_omp_for_set_clauses (gimple g, tree clauses) +Set @code{CLAUSES} to be the list of clauses associated with @code{OMP_FOR} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_omp_for_index (gimple g) +Return the index variable for @code{OMP_FOR} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree *gimple_omp_for_index_ptr (gimple g) +Return a pointer to the index variable for @code{OMP_FOR} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_omp_for_set_index (gimple g, tree index) +Set @code{INDEX} to be the index variable for @code{OMP_FOR} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_omp_for_initial (gimple g) +Return the initial value for @code{OMP_FOR} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree *gimple_omp_for_initial_ptr (gimple g) +Return a pointer to the initial value for @code{OMP_FOR} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_omp_for_set_initial (gimple g, tree initial) +Set @code{INTIAL} to be the initial value for @code{OMP_FOR} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_omp_for_final (gimple g) +Return the final value for @code{OMP_FOR} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree *gimple_omp_for_final_ptr (gimple g) +turn a pointer to the final value for @code{OMP_FOR} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_omp_for_set_final (gimple g, tree final) +Set @code{FINAL} to be the final value for @code{OMP_FOR} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_omp_for_incr (gimple g) +Return the increment value for @code{OMP_FOR} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree *gimple_omp_for_incr_ptr (gimple g) +Return a pointer to the increment value for @code{OMP_FOR} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_omp_for_set_incr (gimple g, tree incr) +Set @code{INCR} to be the increment value for @code{OMP_FOR} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} gimple_seq gimple_omp_for_pre_body (gimple g) +Return the sequence of statements to execute before the @code{OMP_FOR} +statement @code{G} starts. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_omp_for_set_pre_body (gimple g, gimple_seq pre_body) +Set @code{PRE_BODY} to be the sequence of statements to execute before +the @code{OMP_FOR} statement @code{G} starts. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_omp_for_set_cond (gimple g, enum tree_code cond) +Set @code{COND} to be the condition code for @code{OMP_FOR} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} enum tree_code gimple_omp_for_cond (gimple g) +Return the condition code associated with @code{OMP_FOR} @code{G}. +@end deftypefn + + +@node @code{GIMPLE_OMP_MASTER} +@subsection @code{GIMPLE_OMP_MASTER} +@cindex @code{GIMPLE_OMP_MASTER} + +@deftypefn {GIMPLE function} gimple gimple_build_omp_master (gimple_seq body) +Build a @code{GIMPLE_OMP_MASTER} statement. @code{BODY} is the sequence of +statements to be executed by just the master. +@end deftypefn + + +@node @code{GIMPLE_OMP_ORDERED} +@subsection @code{GIMPLE_OMP_ORDERED} +@cindex @code{GIMPLE_OMP_ORDERED} + +@deftypefn {GIMPLE function} gimple gimple_build_omp_ordered (gimple_seq body) +Build a @code{GIMPLE_OMP_ORDERED} statement. +@end deftypefn + +@code{BODY} is the sequence of statements inside a loop that will +executed in sequence. + + +@node @code{GIMPLE_OMP_PARALLEL} +@subsection @code{GIMPLE_OMP_PARALLEL} +@cindex @code{GIMPLE_OMP_PARALLEL} + +@deftypefn {GIMPLE function} gimple gimple_build_omp_parallel (gimple_seq body, tree clauses, tree child_fn, tree data_arg) +Build a @code{GIMPLE_OMP_PARALLEL} statement. +@end deftypefn + +@code{BODY} is sequence of statements which are executed in parallel. +@code{CLAUSES}, are the @code{OMP} parallel construct's clauses. @code{CHILD_FN} is +the function created for the parallel threads to execute. +@code{DATA_ARG} are the shared data argument(s). + +@deftypefn {GIMPLE function} bool gimple_omp_parallel_combined_p (gimple g) +Return true if @code{OMP} parallel statement @code{G} has the +@code{GF_OMP_PARALLEL_COMBINED} flag set. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_omp_parallel_set_combined_p (gimple g) +Set the @code{GF_OMP_PARALLEL_COMBINED} field in @code{OMP} parallel statement +@code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} gimple_seq gimple_omp_body (gimple g) +Return the body for the @code{OMP} statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_omp_set_body (gimple g, gimple_seq body) +Set @code{BODY} to be the body for the @code{OMP} statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_omp_parallel_clauses (gimple g) +Return the clauses associated with @code{OMP_PARALLEL} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree *gimple_omp_parallel_clauses_ptr (gimple g) +Return a pointer to the clauses associated with @code{OMP_PARALLEL} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_omp_parallel_set_clauses (gimple g, tree clauses) +Set @code{CLAUSES} to be the list of clauses associated with +@code{OMP_PARALLEL} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_omp_parallel_child_fn (gimple g) +Return the child function used to hold the body of @code{OMP_PARALLEL} +@code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree *gimple_omp_parallel_child_fn_ptr (gimple g) +Return a pointer to the child function used to hold the body of +@code{OMP_PARALLEL} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_omp_parallel_set_child_fn (gimple g, tree child_fn) +Set @code{CHILD_FN} to be the child function for @code{OMP_PARALLEL} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_omp_parallel_data_arg (gimple g) +Return the artificial argument used to send variables and values +from the parent to the children threads in @code{OMP_PARALLEL} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree *gimple_omp_parallel_data_arg_ptr (gimple g) +Return a pointer to the data argument for @code{OMP_PARALLEL} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_omp_parallel_set_data_arg (gimple g, tree data_arg) +Set @code{DATA_ARG} to be the data argument for @code{OMP_PARALLEL} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} bool is_gimple_omp (gimple stmt) +Returns true when the gimple statment @code{STMT} is any of the OpenMP +types. +@end deftypefn + + +@node @code{GIMPLE_OMP_RETURN} +@subsection @code{GIMPLE_OMP_RETURN} +@cindex @code{GIMPLE_OMP_RETURN} + +@deftypefn {GIMPLE function} gimple gimple_build_omp_return (bool wait_p) +Build a @code{GIMPLE_OMP_RETURN} statement. @code{WAIT_P} is true if this is a +non-waiting return. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_omp_return_set_nowait (gimple s) +Set the nowait flag on @code{GIMPLE_OMP_RETURN} statement @code{S}. +@end deftypefn + + +@deftypefn {GIMPLE function} bool gimple_omp_return_nowait_p (gimple g) +Return true if @code{OMP} return statement @code{G} has the +@code{GF_OMP_RETURN_NOWAIT} flag set. +@end deftypefn + +@node @code{GIMPLE_OMP_SECTION} +@subsection @code{GIMPLE_OMP_SECTION} +@cindex @code{GIMPLE_OMP_SECTION} + +@deftypefn {GIMPLE function} gimple gimple_build_omp_section (gimple_seq body) +Build a @code{GIMPLE_OMP_SECTION} statement for a sections statement. +@end deftypefn + +@code{BODY} is the sequence of statements in the section. + +@deftypefn {GIMPLE function} bool gimple_omp_section_last_p (gimple g) +Return true if @code{OMP} section statement @code{G} has the +@code{GF_OMP_SECTION_LAST} flag set. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_omp_section_set_last (gimple g) +Set the @code{GF_OMP_SECTION_LAST} flag on @code{G}. +@end deftypefn + +@node @code{GIMPLE_OMP_SECTIONS} +@subsection @code{GIMPLE_OMP_SECTIONS} +@cindex @code{GIMPLE_OMP_SECTIONS} + +@deftypefn {GIMPLE function} gimple gimple_build_omp_sections (gimple_seq body, tree clauses) +Build a @code{GIMPLE_OMP_SECTIONS} statement. @code{BODY} is a sequence of +section statements. @code{CLAUSES} are any of the @code{OMP} sections +contsruct's clauses: private, firstprivate, lastprivate, +reduction, and nowait. +@end deftypefn + + +@deftypefn {GIMPLE function} gimple gimple_build_omp_sections_switch (void) +Build a @code{GIMPLE_OMP_SECTIONS_SWITCH} statement. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_omp_sections_control (gimple g) +Return the control variable associated with the +@code{GIMPLE_OMP_SECTIONS} in @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree *gimple_omp_sections_control_ptr (gimple g) +Return a pointer to the clauses associated with the +@code{GIMPLE_OMP_SECTIONS} in @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_omp_sections_set_control (gimple g, tree control) +Set @code{CONTROL} to be the set of clauses associated with the +@code{GIMPLE_OMP_SECTIONS} in @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_omp_sections_clauses (gimple g) +Return the clauses associated with @code{OMP_SECTIONS} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree *gimple_omp_sections_clauses_ptr (gimple g) +Return a pointer to the clauses associated with @code{OMP_SECTIONS} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_omp_sections_set_clauses (gimple g, tree clauses) +Set @code{CLAUSES} to be the set of clauses associated with @code{OMP_SECTIONS} +@code{G}. +@end deftypefn + + +@node @code{GIMPLE_OMP_SINGLE} +@subsection @code{GIMPLE_OMP_SINGLE} +@cindex @code{GIMPLE_OMP_SINGLE} + +@deftypefn {GIMPLE function} gimple gimple_build_omp_single (gimple_seq body, tree clauses) +Build a @code{GIMPLE_OMP_SINGLE} statement. @code{BODY} is the sequence of +statements that will be executed once. @code{CLAUSES} are any of the +@code{OMP} single construct's clauses: private, firstprivate, +copyprivate, nowait. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_omp_single_clauses (gimple g) +Return the clauses associated with @code{OMP_SINGLE} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree *gimple_omp_single_clauses_ptr (gimple g) +Return a pointer to the clauses associated with @code{OMP_SINGLE} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_omp_single_set_clauses (gimple g, tree clauses) +Set @code{CLAUSES} to be the clauses associated with @code{OMP_SINGLE} @code{G}. +@end deftypefn + + +@node @code{GIMPLE_PHI} +@subsection @code{GIMPLE_PHI} +@cindex @code{GIMPLE_PHI} + +@deftypefn {GIMPLE function} gimple make_phi_node (tree var, int len) +Build a @code{PHI} node with len argument slots for variable var. +@end deftypefn + +@deftypefn {GIMPLE function} unsigned gimple_phi_capacity (gimple g) +Return the maximum number of arguments supported by @code{GIMPLE_PHI} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} unsigned gimple_phi_num_args (gimple g) +Return the number of arguments in @code{GIMPLE_PHI} @code{G}. This must always +be exactly the number of incoming edges for the basic block +holding @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_phi_result (gimple g) +Return the @code{SSA} name created by @code{GIMPLE_PHI} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree *gimple_phi_result_ptr (gimple g) +Return a pointer to the @code{SSA} name created by @code{GIMPLE_PHI} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_phi_set_result (gimple g, tree result) +Set @code{RESULT} to be the @code{SSA} name created by @code{GIMPLE_PHI} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} struct phi_arg_d *gimple_phi_arg (gimple g, index) +Return the @code{PHI} argument corresponding to incoming edge @code{INDEX} for +@code{GIMPLE_PHI} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_phi_set_arg (gimple g, index, struct phi_arg_d * phiarg) +Set @code{PHIARG} to be the argument corresponding to incoming edge +@code{INDEX} for @code{GIMPLE_PHI} @code{G}. +@end deftypefn + +@node @code{GIMPLE_RESX} +@subsection @code{GIMPLE_RESX} +@cindex @code{GIMPLE_RESX} + +@deftypefn {GIMPLE function} gimple gimple_build_resx (int region) +Build a @code{GIMPLE_RESX} statement which is a statement. This +statement is a placeholder for _Unwind_Resume before we know if a +function call or a branch is needed. @code{REGION} is the exception +region from which control is flowing. +@end deftypefn + +@deftypefn {GIMPLE function} int gimple_resx_region (gimple g) +Return the region number for @code{GIMPLE_RESX} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_resx_set_region (gimple g, int region) +Set @code{REGION} to be the region number for @code{GIMPLE_RESX} @code{G}. +@end deftypefn + +@node @code{GIMPLE_RETURN} +@subsection @code{GIMPLE_RETURN} +@cindex @code{GIMPLE_RETURN} + +@deftypefn {GIMPLE function} gimple gimple_build_return (tree retval) +Build a @code{GIMPLE_RETURN} statement whose return value is retval. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_return_retval (gimple g) +Return the return value for @code{GIMPLE_RETURN} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_return_set_retval (gimple g, tree retval) +Set @code{RETVAL} to be the return value for @code{GIMPLE_RETURN} @code{G}. +@end deftypefn + +@node @code{GIMPLE_SWITCH} +@subsection @code{GIMPLE_SWITCH} +@cindex @code{GIMPLE_SWITCH} + +@deftypefn {GIMPLE function} gimple gimple_build_switch ( nlabels, tree index, tree default_label, ...) +Build a @code{GIMPLE_SWITCH} statement. @code{NLABELS} are the number of +labels excluding the default label. The default label is passed +in @code{DEFAULT_LABEL}. The rest of the arguments are trees +representing the labels. Each label is a tree of code +@code{CASE_LABEL_EXPR}. +@end deftypefn + +@deftypefn {GIMPLE function} gimple gimple_build_switch_vec (tree index, tree default_label, @code{VEC}(tree,heap) *args) +This function is an alternate way of building @code{GIMPLE_SWITCH} +statements. @code{INDEX} and @code{DEFAULT_LABEL} are as in +gimple_build_switch. @code{ARGS} is a vector of @code{CASE_LABEL_EXPR} trees +that contain the labels. +@end deftypefn + +@deftypefn {GIMPLE function} unsigned gimple_switch_num_labels (gimple g) +Return the number of labels associated with the switch statement +@code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_switch_set_num_labels (gimple g, unsigned nlabels) +Set @code{NLABELS} to be the number of labels for the switch statement +@code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_switch_index (gimple g) +Return the index variable used by the switch statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_switch_set_index (gimple g, tree index) +Set @code{INDEX} to be the index variable for switch statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_switch_label (gimple g, unsigned index) +Return the label numbered @code{INDEX}. The default label is 0, followed +by any labels in a switch statement. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_switch_set_label (gimple g, unsigned index, tree label) +Set the label number @code{INDEX} to @code{LABEL}. 0 is always the default +label. +@end deftypefn + +@deftypefn {GIMPLE function} tree gimple_switch_default_label (gimple g) +Return the default label for a switch statement. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_switch_set_default_label (gimple g, tree label) +Set the default label for a switch statement. +@end deftypefn + + +@node @code{GIMPLE_TRY} +@subsection @code{GIMPLE_TRY} +@cindex @code{GIMPLE_TRY} + +@deftypefn {GIMPLE function} gimple gimple_build_try (gimple_seq eval, gimple_seq cleanup, unsigned int kind) +Build a @code{GIMPLE_TRY} statement. @code{EVAL} is a sequence with the +expression to evaluate. @code{CLEANUP} is a sequence of statements to +run at clean-up time. @code{KIND} is the enumeration value +@code{GIMPLE_TRY_CATCH} if this statement denotes a try/catch construct +or @code{GIMPLE_TRY_FINALLY} if this statement denotes a try/finally +construct. +@end deftypefn + +@deftypefn {GIMPLE function} enum gimple_try_flags gimple_try_kind (gimple g) +Return the kind of try block represented by @code{GIMPLE_TRY} @code{G}. This is +either @code{GIMPLE_TRY_CATCH} or @code{GIMPLE_TRY_FINALLY}. +@end deftypefn + +@deftypefn {GIMPLE function} bool gimple_try_catch_is_cleanup (gimple g) +Return the @code{GIMPLE_TRY_CATCH_IS_CLEANUP} flag. +@end deftypefn + +@deftypefn {GIMPLE function} gimple_seq gimple_try_eval (gimple g) +Return the sequence of statements used as the body for @code{GIMPLE_TRY} +@code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} gimple_seq gimple_try_cleanup (gimple g) +Return the sequence of statements used as the cleanup body for +@code{GIMPLE_TRY} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_try_set_catch_is_cleanup (gimple g, bool catch_is_cleanup) +Set the @code{GIMPLE_TRY_CATCH_IS_CLEANUP} flag. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_try_set_eval (gimple g, gimple_seq eval) +Set @code{EVAL} to be the sequence of statements to use as the body for +@code{GIMPLE_TRY} @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_try_set_cleanup (gimple g, gimple_seq cleanup) +Set @code{CLEANUP} to be the sequence of statements to use as the +cleanup body for @code{GIMPLE_TRY} @code{G}. +@end deftypefn + +@node @code{GIMPLE_WITH_CLEANUP_EXPR} +@subsection @code{GIMPLE_WITH_CLEANUP_EXPR} +@cindex @code{GIMPLE_WITH_CLEANUP_EXPR} + +@deftypefn {GIMPLE function} gimple gimple_build_wce (gimple_seq cleanup) +Build a @code{GIMPLE_WITH_CLEANUP_EXPR} statement. @code{CLEANUP} is the +clean-up expression. +@end deftypefn + +@deftypefn {GIMPLE function} gimple_seq gimple_wce_cleanup (gimple g) +Return the cleanup sequence for cleanup statement @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_wce_set_canup (gimple g, gimple_seq cleanup) +Set @code{CLEANUP} to be the cleanup sequence for @code{G}. +@end deftypefn + +@deftypefn {GIMPLE function} bool gimple_wce_cleanup_eh_only (gimple g) +Return the @code{CLEANUP_EH_ONLY} flag for a @code{WCE} tuple. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_wce_set_cleanup_eh_only (gimple g, bool eh_only_p) +Set the @code{CLEANUP_EH_ONLY} flag for a @code{WCE} tuple. +@end deftypefn + + +@node GIMPLE sequences +@section GIMPLE sequences +@cindex GIMPLE sequences + +GIMPLE sequences are the tuple equivalent of @code{STATEMENT_LIST}'s +used in @code{GENERIC}. They are used to chain statements together, and +when used in conjunction with sequence iterators, provide a +framework for iterating through statements. + +GIMPLE sequences are of type struct @code{gimple_sequence}, but are more +commonly passed by reference to functions dealing with sequences. +The type for a sequence pointer is @code{gimple_seq} which is the same +as struct @code{gimple_sequence} *. When declaring a local sequence, +you can define a local variable of type struct @code{gimple_sequence}. +When declaring a sequence allocated on the garbage collected +heap, use the function @code{gimple_seq_alloc} documented below. + +There are convenience functions for iterating through sequences +in the section entitled Sequence Iterators. + +Below is a list of functions to manipulate and query sequences. + +@deftypefn {GIMPLE function} void gimple_seq_add_stmt (gimple_seq *seq, gimple g) +Link a gimple statement to the end of the sequence *@code{SEQ} if @code{G} is +not @code{NULL}. If *@code{SEQ} is @code{NULL}, allocate a sequence before linking. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_seq_add_seq (gimple_seq *dest, gimple_seq src) +Append sequence @code{SRC} to the end of sequence *@code{DEST} if @code{SRC} is not +@code{NULL}. If *@code{DEST} is @code{NULL}, allocate a new sequence before +appending. +@end deftypefn + +@deftypefn {GIMPLE function} gimple_seq gimple_seq_deep_copy (gimple_seq src) +Perform a deep copy of sequence @code{SRC} and return the result. +@end deftypefn + +@deftypefn {GIMPLE function} gimple_seq gimple_seq_reverse (gimple_seq seq) +Reverse the order of the statements in the sequence @code{SEQ}. Return +@code{SEQ}. +@end deftypefn + +@deftypefn {GIMPLE function} gimple gimple_seq_first (gimple_seq s) +Return the first statement in sequence @code{S}. +@end deftypefn + +@deftypefn {GIMPLE function} gimple gimple_seq_last (gimple_seq s) +Return the last statement in sequence @code{S}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_seq_set_last (gimple_seq s, gimple last) +Set the last statement in sequence @code{S} to the statement in @code{LAST}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_seq_set_first (gimple_seq s, gimple first) +Set the first statement in sequence @code{S} to the statement in @code{FIRST}. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_seq_init (gimple_seq s) +Initialize sequence @code{S} to an empty sequence. +@end deftypefn + +@deftypefn {GIMPLE function} gimple_seq gimple_seq_alloc (void) +Allocate a new sequence in the garbage collected store and return +it. +@end deftypefn + +@deftypefn {GIMPLE function} void gimple_seq_copy (gimple_seq dest, gimple_seq src) +Copy the sequence @code{SRC} into the sequence @code{DEST}. +@end deftypefn + +@deftypefn {GIMPLE function} bool gimple_seq_empty_p (gimple_seq s) +Return true if the sequence @code{S} is empty. +@end deftypefn + +@deftypefn {GIMPLE function} gimple_seq bb_seq (basic_block bb) +Returns the sequence of statements in @code{BB}. +@end deftypefn + +@deftypefn {GIMPLE function} void set_bb_seq (basic_block bb, gimple_seq seq) +Sets the sequence of statements in @code{BB} to @code{SEQ}. +@end deftypefn + +@deftypefn {GIMPLE function} bool gimple_seq_singleton_p (gimple_seq seq) +Determine whether @code{SEQ} contains exactly one statement. +@end deftypefn + +@node Sequence iterators +@section Sequence iterators +@cindex Sequence iterators + +Sequence iterators are convenience constructs for iterating +through statements in a sequence. Given a sequence @code{SEQ}, here is +a typical use of gimple sequence iterators: + +@smallexample +gimple_stmt_iterator gsi; + +for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi)) + @{ + gimple g = gsi_stmt (gsi); + /* Do something with gimple statement @code{G}. */ + @} +@end smallexample + +Backward iterations are possible: + +@smallexample + for (gsi = gsi_last (seq); !gsi_end_p (gsi); gsi_prev (&gsi)) +@end smallexample + +Forward and backward iterations on basic blocks are possible with +@code{gsi_start_bb} and @code{gsi_last_bb}. + +In the documentation below we sometimes refer to enum +@code{gsi_iterator_update}. The valid options for this enumeration are: + +@itemize @bullet +@item @code{GSI_NEW_STMT} +Only valid when a single statement is added. Move the iterator to it. + +@item @code{GSI_SAME_STMT} +Leave the iterator at the same statement. + +@item @code{GSI_CONTINUE_LINKING} +Move iterator to whatever position is suitable for linking other +statements in the same direction. +@end itemize + +Below is a list of the functions used to manipulate and use +statement iterators. + +@deftypefn {GIMPLE function} gimple_stmt_iterator gsi_start (gimple_seq seq) +Return a new iterator pointing to the sequence @code{SEQ}'s first +statement. If @code{SEQ} is empty, the iterator's basic block is @code{NULL}. +Use @code{gsi_start_bb} instead when the iterator needs to always have +the correct basic block set. +@end deftypefn + +@deftypefn {GIMPLE function} gimple_stmt_iterator gsi_start_bb (basic_block bb) +Return a new iterator pointing to the first statement in basic +block @code{BB}. +@end deftypefn + +@deftypefn {GIMPLE function} gimple_stmt_iterator gsi_last (gimple_seq seq) +Return a new iterator initially pointing to the last statement of +sequence @code{SEQ}. If @code{SEQ} is empty, the iterator's basic block is +@code{NULL}. Use @code{gsi_last_bb} instead when the iterator needs to always +have the correct basic block set. +@end deftypefn + +@deftypefn {GIMPLE function} gimple_stmt_iterator gsi_last_bb (basic_block bb) +Return a new iterator pointing to the last statement in basic +block @code{BB}. +@end deftypefn + +@deftypefn {GIMPLE function} bool gsi_end_p (gimple_stmt_iterator i) +Return @code{TRUE} if at the end of @code{I}. +@end deftypefn + +@deftypefn {GIMPLE function} bool gsi_one_before_end_p (gimple_stmt_iterator i) +Return @code{TRUE} if we're one statement before the end of @code{I}. +@end deftypefn + +@deftypefn {GIMPLE function} void gsi_next (gimple_stmt_iterator *i) +Advance the iterator to the next gimple statement. +@end deftypefn + +@deftypefn {GIMPLE function} void gsi_prev (gimple_stmt_iterator *i) +Advance the iterator to the previous gimple statement. +@end deftypefn + +@deftypefn {GIMPLE function} gimple gsi_stmt (gimple_stmt_iterator i) +Return the current stmt. +@end deftypefn + +@deftypefn {GIMPLE function} gimple_stmt_iterator gsi_after_labels (basic_block bb) +Return a block statement iterator that points to the first +non-label statement in block @code{BB}. +@end deftypefn + +@deftypefn {GIMPLE function} gimple *gsi_stmt_ptr (gimple_stmt_iterator *i) +Return a pointer to the current stmt. +@end deftypefn + +@deftypefn {GIMPLE function} basic_block gsi_bb (gimple_stmt_iterator i) +Return the basic block associated with this iterator. +@end deftypefn + +@deftypefn {GIMPLE function} gimple_seq gsi_seq (gimple_stmt_iterator i) +Return the sequence associated with this iterator. +@end deftypefn + +@deftypefn {GIMPLE function} void gsi_remove (gimple_stmt_iterator *i, bool remove_eh_info) +Remove the current stmt from the sequence. The iterator is +updated to point to the next statement. When @code{REMOVE_EH_INFO} is +true we remove the statement pointed to by iterator @code{I} from the @code{EH} +tables. Otherwise we do not modify the @code{EH} tables. Generally, +@code{REMOVE_EH_INFO} should be true when the statement is going to be +removed from the @code{IL} and not reinserted elsewhere. +@end deftypefn + +@deftypefn {GIMPLE function} void gsi_link_seq_before (gimple_stmt_iterator *i, gimple_seq seq, enum gsi_iterator_update mode) +Links the sequence of statements @code{SEQ} before the statement pointed +by iterator @code{I}. @code{MODE} indicates what to do with the iterator +after insertion (see @code{enum gsi_iterator_update} above). +@end deftypefn + +@deftypefn {GIMPLE function} void gsi_link_before (gimple_stmt_iterator *i, gimple g, enum gsi_iterator_update mode) +Links statement @code{G} before the statement pointed-to by iterator @code{I}. +Updates iterator @code{I} according to @code{MODE}. +@end deftypefn + +@deftypefn {GIMPLE function} void gsi_link_seq_after (gimple_stmt_iterator *i, gimple_seq seq, enum gsi_iterator_update mode) +Links sequence @code{SEQ} after the statement pointed-to by iterator @code{I}. +@code{MODE} is as in @code{gsi_insert_after}. +@end deftypefn + +@deftypefn {GIMPLE function} void gsi_link_after (gimple_stmt_iterator *i, gimple g, enum gsi_iterator_update mode) +Links statement @code{G} after the statement pointed-to by iterator @code{I}. +@code{MODE} is as in @code{gsi_insert_after}. +@end deftypefn + +@deftypefn {GIMPLE function} gimple_seq gsi_split_seq_after (gimple_stmt_iterator i) +Move all statements in the sequence after @code{I} to a new sequence. +Return this new sequence. +@end deftypefn + +@deftypefn {GIMPLE function} gimple_seq gsi_split_seq_before (gimple_stmt_iterator *i) +Move all statements in the sequence before @code{I} to a new sequence. +Return this new sequence. +@end deftypefn + +@deftypefn {GIMPLE function} void gsi_replace (gimple_stmt_iterator *i, gimple stmt, bool update_eh_info) +Replace the statement pointed-to by @code{I} to @code{STMT}. If @code{UPDATE_EH_INFO} +is true, the exception handling information of the original +statement is moved to the new statement. +@end deftypefn + +@deftypefn {GIMPLE function} void gsi_insert_before (gimple_stmt_iterator *i, gimple stmt, enum gsi_iterator_update mode) +Insert statement @code{STMT} before the statement pointed-to by iterator +@code{I}, update @code{STMT}'s basic block and scan it for new operands. @code{MODE} +specifies how to update iterator @code{I} after insertion (see enum +@code{gsi_iterator_update}). +@end deftypefn + +@deftypefn {GIMPLE function} void gsi_insert_seq_before (gimple_stmt_iterator *i, gimple_seq seq, enum gsi_iterator_update mode) +Like @code{gsi_insert_before}, but for all the statements in @code{SEQ}. +@end deftypefn + +@deftypefn {GIMPLE function} void gsi_insert_after (gimple_stmt_iterator *i, gimple stmt, enum gsi_iterator_update mode) +Insert statement @code{STMT} after the statement pointed-to by iterator +@code{I}, update @code{STMT}'s basic block and scan it for new operands. @code{MODE} +specifies how to update iterator @code{I} after insertion (see enum +@code{gsi_iterator_update}). +@end deftypefn + +@deftypefn {GIMPLE function} void gsi_insert_seq_after (gimple_stmt_iterator *i, gimple_seq seq, enum gsi_iterator_update mode) +Like @code{gsi_insert_after}, but for all the statements in @code{SEQ}. +@end deftypefn + +@deftypefn {GIMPLE function} gimple_stmt_iterator gsi_for_stmt (gimple stmt) +Finds iterator for @code{STMT}. +@end deftypefn + +@deftypefn {GIMPLE function} void gsi_move_after (gimple_stmt_iterator *from, gimple_stmt_iterator *to) +Move the statement at @code{FROM} so it comes right after the statement +at @code{TO}. +@end deftypefn + +@deftypefn {GIMPLE function} void gsi_move_before (gimple_stmt_iterator *from, gimple_stmt_iterator *to) +Move the statement at @code{FROM} so it comes right before the statement +at @code{TO}. +@end deftypefn + +@deftypefn {GIMPLE function} void gsi_move_to_bb_end (gimple_stmt_iterator *from, basic_block bb) +Move the statement at @code{FROM} to the end of basic block @code{BB}. +@end deftypefn + +@deftypefn {GIMPLE function} void gsi_insert_on_edge (edge e, gimple stmt) +Add @code{STMT} to the pending list of edge @code{E}. No actual insertion is +made until a call to @code{gsi_commit_edge_inserts}() is made. +@end deftypefn + +@deftypefn {GIMPLE function} void gsi_insert_seq_on_edge (edge e, gimple_seq seq) +Add the sequence of statements in @code{SEQ} to the pending list of edge +@code{E}. No actual insertion is made until a call to +@code{gsi_commit_edge_inserts}() is made. +@end deftypefn + +@deftypefn {GIMPLE function} basic_block gsi_insert_on_edge_immediate (edge e, gimple stmt) +Similar to @code{gsi_insert_on_edge}+@code{gsi_commit_edge_inserts}. If a new +block has to be created, it is returned. +@end deftypefn + +@deftypefn {GIMPLE function} void gsi_commit_one_edge_insert (edge e, basic_block *new_bb) +Commit insertions pending at edge @code{E}. If a new block is created, +set @code{NEW_BB} to this block, otherwise set it to @code{NULL}. +@end deftypefn + +@deftypefn {GIMPLE function} void gsi_commit_edge_inserts (void) +This routine will commit all pending edge insertions, creating +any new basic blocks which are necessary. +@end deftypefn + + +@node Adding a new GIMPLE statement code +@section Adding a new GIMPLE statement code +@cindex Adding a new GIMPLE statement code + +The first step in adding a new GIMPLE statement code, is +modifying the file @code{gimple.def}, which contains all the GIMPLE +codes. Then you must add a corresponding structure, and an entry +in @code{union gimple_statement_d}, both of which are located in +@code{gimple.h}. This in turn, will require you to add a corresponding +@code{GTY} tag in @code{gsstruct.def}, and code to handle this tag in +@code{gss_for_code} which is located in @code{gimple.c}. + +In order for the garbage collector to know the size of the +structure you created in @code{gimple.h}, you need to add a case to +handle your new GIMPLE statement in @code{gimple_size} which is located +in @code{gimple.c}. + +You will probably want to create a function to build the new +gimple statement in @code{gimple.c}. The function should be called +@code{gimple_build_<@code{NEW_TUPLE_NAME}>}, and should return the new tuple +of type gimple. + +If your new statement requires accessors for any members or +operands it may have, put simple inline accessors in +@code{gimple.h} and any non-trivial accessors in @code{gimple.c} with a +corresponding prototype in @code{gimple.h}. + + +@node Statement and operand traversals +@section Statement and operand traversals +@cindex Statement and operand traversals + +There are two functions available for walking statements and +sequences: @code{walk_gimple_stmt} and @code{walk_gimple_seq}, +accordingly, and a third function for walking the operands in a +statement: @code{walk_gimple_op}. + +@deftypefn {GIMPLE function} tree walk_gimple_stmt (gimple_stmt_iterator *gsi, walk_stmt_fn callback_stmt, walk_tree_fn callback_op, struct walk_stmt_info *wi) +This function is used to walk the current statement in @code{GSI}, +optionally using traversal state stored in @code{WI}. If @code{WI} is @code{NULL}, no +state is kept during the traversal. + +The callback @code{CALLBACK_STMT} is called. If @code{CALLBACK_STMT} returns +true, it means that the callback function has handled all the +operands of the statement and it is not necessary to walk its +operands. + +If @code{CALLBACK_STMT} is @code{NULL} or it returns false, @code{CALLBACK_OP} is +called on each operand of the statement via @code{walk_gimple_op}. If +@code{walk_gimple_op} returns non-@code{NULL} for any operand, the remaining +operands are not scanned. + +The return value is that returned by the last call to +@code{walk_gimple_op}, or @code{NULL_TREE} if no @code{CALLBACK_OP} is specified. +@end deftypefn + + +@deftypefn {GIMPLE function} tree walk_gimple_op (gimple stmt, walk_tree_fn callback_op, struct walk_stmt_info *wi) +Use this function to walk the operands of statement @code{STMT}. Every +operand is walked via @code{walk_tree} with optional state information +in @code{WI}. + +@code{CALLBACK_OP} is called on each operand of @code{STMT} via @code{walk_tree}. +Additional parameters to @code{walk_tree} must be stored in @code{WI}. For +each operand @code{OP}, @code{walk_tree} is called as: + +@smallexample + walk_tree (&@code{OP}, @code{CALLBACK_OP}, @code{WI}, @code{WI}- @code{PSET}) +@end smallexample + +If @code{CALLBACK_OP} returns non-@code{NULL} for an operand, the remaining +operands are not scanned. The return value is that returned by +the last call to @code{walk_tree}, or @code{NULL_TREE} if no @code{CALLBACK_OP} is +specified. +@end deftypefn + + +@deftypefn {GIMPLE function} tree walk_gimple_seq (gimple_seq seq, walk_stmt_fn callback_stmt, walk_tree_fn callback_op, struct walk_stmt_info *wi) +This function walks all the statements in the sequence @code{SEQ} +calling @code{walk_gimple_stmt} on each one. @code{WI} is as in +@code{walk_gimple_stmt}. If @code{walk_gimple_stmt} returns non-@code{NULL}, the walk +is stopped and the value returned. Otherwise, all the statements +are walked and @code{NULL_TREE} returned. +@end deftypefn diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index eba39cde164..dbff5761efe 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -2826,17 +2826,26 @@ as below: @end smallexample @end defmac -@defmac IRA_COVER_CLASSES -The macro defines cover classes for the Integrated Register Allocator +@deftypefn {Target Hook} {const enum reg_class *} TARGET_IRA_COVER_CLASSES () +Return an array of cover classes for the Integrated Register Allocator (@acronym{IRA}). Cover classes are a set of non-intersecting register classes covering all hard registers used for register allocation purposes. If a move between two registers in the same cover class is possible, it should be cheaper than a load or store of the registers. -The macro value should be the initializer for an array of register -class values, with @code{LIM_REG_CLASSES} used as the end marker. +The array is terminated by a @code{LIM_REG_CLASSES} element. + +This hook is called once at compiler startup, after the command-line +options have been processed. It is then re-examined by every call to +@code{target_reinit}. -You must define this macro in order to use the integrated register +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. +@end deftypefn + +@defmac IRA_COVER_CLASSES +See the documentation for @code{TARGET_IRA_COVER_CLASSES}. @end defmac @node Old Constraints diff --git a/gcc/doc/tree-ssa.texi b/gcc/doc/tree-ssa.texi index ea3d0ab4c59..bd0edc44226 100644 --- a/gcc/doc/tree-ssa.texi +++ b/gcc/doc/tree-ssa.texi @@ -8,7 +8,7 @@ @c --------------------------------------------------------------------- @node Tree SSA -@chapter Analysis and Optimization of GIMPLE Trees +@chapter Analysis and Optimization of GIMPLE tuples @cindex Tree SSA @cindex Optimization infrastructure for GIMPLE @@ -37,728 +37,28 @@ functions and programming constructs needed to implement optimization passes for GIMPLE@. @menu -* GENERIC:: A high-level language-independent representation. -* GIMPLE:: A lower-level factored tree representation. -* Annotations:: Attributes for statements and variables. -* Statement Operands:: Variables referenced by GIMPLE statements. +* Annotations:: Attributes for variables. +* SSA Operands:: SSA names referenced by GIMPLE statements. * SSA:: Static Single Assignment representation. * Alias analysis:: Representing aliased loads and stores. @end menu -@node GENERIC -@section GENERIC -@cindex GENERIC - -The purpose of GENERIC is simply to provide a language-independent way of -representing an entire function in trees. To this end, it was necessary to -add a few new tree codes to the back end, but most everything was already -there. If you can express it with the codes in @code{gcc/tree.def}, it's -GENERIC@. - -Early on, there was a great deal of debate about how to think about -statements in a tree IL@. In GENERIC, a statement is defined as any -expression whose value, if any, is ignored. A statement will always -have @code{TREE_SIDE_EFFECTS} set (or it will be discarded), but a -non-statement expression may also have side effects. A -@code{CALL_EXPR}, for instance. - -It would be possible for some local optimizations to work on the -GENERIC form of a function; indeed, the adapted tree inliner works -fine on GENERIC, but the current compiler performs inlining after -lowering to GIMPLE (a restricted form described in the next section). -Indeed, currently the frontends perform this lowering before handing -off to @code{tree_rest_of_compilation}, but this seems inelegant. - -If necessary, a front end can use some language-dependent tree codes -in its GENERIC representation, so long as it provides a hook for -converting them to GIMPLE and doesn't expect them to work with any -(hypothetical) optimizers that run before the conversion to GIMPLE@. -The intermediate representation used while parsing C and C++ looks -very little like GENERIC, but the C and C++ gimplifier hooks are -perfectly happy to take it as input and spit out GIMPLE@. - -@node GIMPLE -@section GIMPLE -@cindex GIMPLE - -GIMPLE is a simplified subset of GENERIC for use in optimization. The -particular subset chosen (and the name) was heavily influenced by the -SIMPLE IL used by the McCAT compiler project at McGill University, -though we have made some different choices. For one thing, SIMPLE -doesn't support @code{goto}; a production compiler can't afford that -kind of restriction. - -GIMPLE retains much of the structure of the parse trees: lexical -scopes are represented as containers, rather than markers. However, -expressions are broken down into a 3-address form, using temporary -variables to hold intermediate values. Also, control structures are -lowered to gotos. - -In GIMPLE no container node is ever used for its value; if a -@code{COND_EXPR} or @code{BIND_EXPR} has a value, it is stored into a -temporary within the controlled blocks, and that temporary is used in -place of the container. - -The compiler pass which lowers GENERIC to GIMPLE is referred to as the -@samp{gimplifier}. The gimplifier works recursively, replacing complex -statements with sequences of simple statements. - -@c Currently, the only way to -@c tell whether or not an expression is in GIMPLE form is by recursively -@c examining it; in the future there will probably be a flag to help avoid -@c redundant work. FIXME FIXME - -@menu -* Interfaces:: -* Temporaries:: -* GIMPLE Expressions:: -* Statements:: -* GIMPLE Example:: -* Rough GIMPLE Grammar:: -@end menu - -@node Interfaces -@subsection Interfaces -@cindex gimplification - -The tree representation of a function is stored in -@code{DECL_SAVED_TREE}. It is lowered to GIMPLE by a call to -@code{gimplify_function_tree}. - -If a front end wants to include language-specific tree codes in the tree -representation which it provides to the back end, it must provide a -definition of @code{LANG_HOOKS_GIMPLIFY_EXPR} which knows how to -convert the front end trees to GIMPLE@. Usually such a hook will involve -much of the same code for expanding front end trees to RTL@. This function -can return fully lowered GIMPLE, or it can return GENERIC trees and let the -main gimplifier lower them the rest of the way; this is often simpler. -GIMPLE that is not fully lowered is known as ``high GIMPLE'' and -consists of the IL before the pass @code{pass_lower_cf}. High GIMPLE -still contains lexical scopes and nested expressions, while low GIMPLE -exposes all of the implicit jumps for control expressions like -@code{COND_EXPR}. - -The C and C++ front ends currently convert directly from front end -trees to GIMPLE, and hand that off to the back end rather than first -converting to GENERIC@. Their gimplifier hooks know about all the -@code{_STMT} nodes and how to convert them to GENERIC forms. There -was some work done on a genericization pass which would run first, but -the existence of @code{STMT_EXPR} meant that in order to convert all -of the C statements into GENERIC equivalents would involve walking the -entire tree anyway, so it was simpler to lower all the way. This -might change in the future if someone writes an optimization pass -which would work better with higher-level trees, but currently the -optimizers all expect GIMPLE@. - -A front end which wants to use the tree optimizers (and already has -some sort of whole-function tree representation) only needs to provide -a definition of @code{LANG_HOOKS_GIMPLIFY_EXPR}, call -@code{gimplify_function_tree} to lower to GIMPLE, and then hand off to -@code{tree_rest_of_compilation} to compile and output the function. - -You can tell the compiler to dump a C-like representation of the GIMPLE -form with the flag @option{-fdump-tree-gimple}. - -@node Temporaries -@subsection Temporaries -@cindex Temporaries - -When gimplification encounters a subexpression which is too complex, it -creates a new temporary variable to hold the value of the subexpression, -and adds a new statement to initialize it before the current statement. -These special temporaries are known as @samp{expression temporaries}, and are -allocated using @code{get_formal_tmp_var}. The compiler tries to -always evaluate identical expressions into the same temporary, to simplify -elimination of redundant calculations. - -We can only use expression temporaries when we know that it will not be -reevaluated before its value is used, and that it will not be otherwise -modified@footnote{These restrictions are derived from those in Morgan 4.8.}. -Other temporaries can be allocated using -@code{get_initialized_tmp_var} or @code{create_tmp_var}. - -Currently, an expression like @code{a = b + 5} is not reduced any -further. We tried converting it to something like -@smallexample - T1 = b + 5; - a = T1; -@end smallexample -but this bloated the representation for minimal benefit. However, a -variable which must live in memory cannot appear in an expression; its -value is explicitly loaded into a temporary first. Similarly, storing -the value of an expression to a memory variable goes through a -temporary. - -@node GIMPLE Expressions -@subsection Expressions -@cindex GIMPLE Expressions - -In general, expressions in GIMPLE consist of an operation and the -appropriate number of simple operands; these operands must either be a -GIMPLE rvalue (@code{is_gimple_val}), i.e.@: a constant or a register -variable. More complex operands are factored out into temporaries, so -that -@smallexample - a = b + c + d -@end smallexample -becomes -@smallexample - T1 = b + c; - a = T1 + d; -@end smallexample - -The same rule holds for arguments to a @code{CALL_EXPR}. - -The target of an assignment is usually a variable, but can also be an -@code{INDIRECT_REF} or a compound lvalue as described below. - -@menu -* Compound Expressions:: -* Compound Lvalues:: -* Conditional Expressions:: -* Logical Operators:: -@end menu - -@node Compound Expressions -@subsubsection Compound Expressions -@cindex Compound Expressions - -The left-hand side of a C comma expression is simply moved into a separate -statement. - -@node Compound Lvalues -@subsubsection Compound Lvalues -@cindex Compound Lvalues - -Currently compound lvalues involving array and structure field references -are not broken down; an expression like @code{a.b[2] = 42} is not reduced -any further (though complex array subscripts are). This restriction is a -workaround for limitations in later optimizers; if we were to convert this -to - -@smallexample - T1 = &a.b; - T1[2] = 42; -@end smallexample - -alias analysis would not remember that the reference to @code{T1[2]} came -by way of @code{a.b}, so it would think that the assignment could alias -another member of @code{a}; this broke @code{struct-alias-1.c}. Future -optimizer improvements may make this limitation unnecessary. - -@node Conditional Expressions -@subsubsection Conditional Expressions -@cindex Conditional Expressions - -A C @code{?:} expression is converted into an @code{if} statement with -each branch assigning to the same temporary. So, - -@smallexample - a = b ? c : d; -@end smallexample -becomes -@smallexample - if (b) - T1 = c; - else - T1 = d; - a = T1; -@end smallexample - -Tree level if-conversion pass re-introduces @code{?:} expression, if appropriate. -It is used to vectorize loops with conditions using vector conditional operations. - -Note that in GIMPLE, @code{if} statements are also represented using -@code{COND_EXPR}, as described below. - -@node Logical Operators -@subsubsection Logical Operators -@cindex Logical Operators - -Except when they appear in the condition operand of a @code{COND_EXPR}, -logical `and' and `or' operators are simplified as follows: -@code{a = b && c} becomes - -@smallexample - T1 = (bool)b; - if (T1) - T1 = (bool)c; - a = T1; -@end smallexample - -Note that @code{T1} in this example cannot be an expression temporary, -because it has two different assignments. - -@node Statements -@subsection Statements -@cindex Statements - -Most statements will be assignment statements, represented by -@code{MODIFY_EXPR}. A @code{CALL_EXPR} whose value is ignored can -also be a statement. No other C expressions can appear at statement level; -a reference to a volatile object is converted into a @code{MODIFY_EXPR}. -In GIMPLE form, type of @code{MODIFY_EXPR} is not meaningful. Instead, use type -of LHS or RHS@. - -There are also several varieties of complex statements. - -@menu -* Blocks:: -* Statement Sequences:: -* Empty Statements:: -* Loops:: -* Selection Statements:: -* Jumps:: -* Cleanups:: -* GIMPLE Exception Handling:: -@end menu - -@node Blocks -@subsubsection Blocks -@cindex Blocks - -Block scopes and the variables they declare in GENERIC and GIMPLE are -expressed using the @code{BIND_EXPR} code, which in previous versions of -GCC was primarily used for the C statement-expression extension. - -Variables in a block are collected into @code{BIND_EXPR_VARS} in -declaration order. Any runtime initialization is moved out of -@code{DECL_INITIAL} and into a statement in the controlled block. When -gimplifying from C or C++, this initialization replaces the -@code{DECL_STMT}. - -Variable-length arrays (VLAs) complicate this process, as their size often -refers to variables initialized earlier in the block. To handle this, we -currently split the block at that point, and move the VLA into a new, inner -@code{BIND_EXPR}. This strategy may change in the future. - -@code{DECL_SAVED_TREE} for a GIMPLE function will always be a -@code{BIND_EXPR} which contains declarations for the temporary variables -used in the function. - -A C++ program will usually contain more @code{BIND_EXPR}s than there are -syntactic blocks in the source code, since several C++ constructs have -implicit scopes associated with them. On the other hand, although the C++ -front end uses pseudo-scopes to handle cleanups for objects with -destructors, these don't translate into the GIMPLE form; multiple -declarations at the same level use the same @code{BIND_EXPR}. - -@node Statement Sequences -@subsubsection Statement Sequences -@cindex Statement Sequences - -Multiple statements at the same nesting level are collected into a -@code{STATEMENT_LIST}. Statement lists are modified and traversed -using the interface in @samp{tree-iterator.h}. - -@node Empty Statements -@subsubsection Empty Statements -@cindex Empty Statements - -Whenever possible, statements with no effect are discarded. But if they -are nested within another construct which cannot be discarded for some -reason, they are instead replaced with an empty statement, generated by -@code{build_empty_stmt}. Initially, all empty statements were shared, -after the pattern of the Java front end, but this caused a lot of trouble in -practice. - -An empty statement is represented as @code{(void)0}. - -@node Loops -@subsubsection Loops -@cindex Loops - -At one time loops were expressed in GIMPLE using @code{LOOP_EXPR}, but -now they are lowered to explicit gotos. - -@node Selection Statements -@subsubsection Selection Statements -@cindex Selection Statements - -A simple selection statement, such as the C @code{if} statement, is -expressed in GIMPLE using a void @code{COND_EXPR}. If only one branch is -used, the other is filled with an empty statement. - -Normally, the condition expression is reduced to a simple comparison. If -it is a shortcut (@code{&&} or @code{||}) expression, however, we try to -break up the @code{if} into multiple @code{if}s so that the implied shortcut -is taken directly, much like the transformation done by @code{do_jump} in -the RTL expander. - -A @code{SWITCH_EXPR} in GIMPLE contains the condition and a -@code{TREE_VEC} of @code{CASE_LABEL_EXPR}s describing the case values -and corresponding @code{LABEL_DECL}s to jump to. The body of the -@code{switch} is moved after the @code{SWITCH_EXPR}. - -@node Jumps -@subsubsection Jumps -@cindex Jumps - -Other jumps are expressed by either @code{GOTO_EXPR} or @code{RETURN_EXPR}. - -The operand of a @code{GOTO_EXPR} must be either a label or a variable -containing the address to jump to. - -The operand of a @code{RETURN_EXPR} is either @code{NULL_TREE}, -@code{RESULT_DECL}, or a @code{MODIFY_EXPR} which sets the return value. It -would be nice to move the @code{MODIFY_EXPR} into a separate statement, but the -special return semantics in @code{expand_return} make that difficult. It may -still happen in the future, perhaps by moving most of that logic into -@code{expand_assignment}. - -@node Cleanups -@subsubsection Cleanups -@cindex Cleanups - -Destructors for local C++ objects and similar dynamic cleanups are -represented in GIMPLE by a @code{TRY_FINALLY_EXPR}. -@code{TRY_FINALLY_EXPR} has two operands, both of which are a sequence -of statements to execute. The first sequence is executed. When it -completes the second sequence is executed. - -The first sequence may complete in the following ways: - -@enumerate - -@item Execute the last statement in the sequence and fall off the -end. - -@item Execute a goto statement (@code{GOTO_EXPR}) to an ordinary -label outside the sequence. - -@item Execute a return statement (@code{RETURN_EXPR}). - -@item Throw an exception. This is currently not explicitly represented in -GIMPLE. - -@end enumerate - -The second sequence is not executed if the first sequence completes by -calling @code{setjmp} or @code{exit} or any other function that does -not return. The second sequence is also not executed if the first -sequence completes via a non-local goto or a computed goto (in general -the compiler does not know whether such a goto statement exits the -first sequence or not, so we assume that it doesn't). - -After the second sequence is executed, if it completes normally by -falling off the end, execution continues wherever the first sequence -would have continued, by falling off the end, or doing a goto, etc. - -@code{TRY_FINALLY_EXPR} complicates the flow graph, since the cleanup -needs to appear on every edge out of the controlled block; this -reduces the freedom to move code across these edges. Therefore, the -EH lowering pass which runs before most of the optimization passes -eliminates these expressions by explicitly adding the cleanup to each -edge. Rethrowing the exception is represented using @code{RESX_EXPR}. - - -@node GIMPLE Exception Handling -@subsubsection Exception Handling -@cindex GIMPLE Exception Handling - -Other exception handling constructs are represented using -@code{TRY_CATCH_EXPR}. @code{TRY_CATCH_EXPR} has two operands. The -first operand is a sequence of statements to execute. If executing -these statements does not throw an exception, then the second operand -is ignored. Otherwise, if an exception is thrown, then the second -operand of the @code{TRY_CATCH_EXPR} is checked. The second operand -may have the following forms: - -@enumerate - -@item A sequence of statements to execute. When an exception occurs, -these statements are executed, and then the exception is rethrown. - -@item A sequence of @code{CATCH_EXPR} expressions. Each @code{CATCH_EXPR} -has a list of applicable exception types and handler code. If the -thrown exception matches one of the caught types, the associated -handler code is executed. If the handler code falls off the bottom, -execution continues after the original @code{TRY_CATCH_EXPR}. - -@item An @code{EH_FILTER_EXPR} expression. This has a list of -permitted exception types, and code to handle a match failure. If the -thrown exception does not match one of the allowed types, the -associated match failure code is executed. If the thrown exception -does match, it continues unwinding the stack looking for the next -handler. - -@end enumerate - -Currently throwing an exception is not directly represented in GIMPLE, -since it is implemented by calling a function. At some point in the future -we will want to add some way to express that the call will throw an -exception of a known type. - -Just before running the optimizers, the compiler lowers the high-level -EH constructs above into a set of @samp{goto}s, magic labels, and EH -regions. Continuing to unwind at the end of a cleanup is represented -with a @code{RESX_EXPR}. - -@node GIMPLE Example -@subsection GIMPLE Example -@cindex GIMPLE Example - -@smallexample -struct A @{ A(); ~A(); @}; - -int i; -int g(); -void f() -@{ - A a; - int j = (--i, i ? 0 : 1); - - for (int x = 42; x > 0; --x) - @{ - i += g()*4 + 32; - @} -@} -@end smallexample - -becomes - -@smallexample -void f() -@{ - int i.0; - int T.1; - int iftmp.2; - int T.3; - int T.4; - int T.5; - int T.6; - - @{ - struct A a; - int j; - - __comp_ctor (&a); - try - @{ - i.0 = i; - T.1 = i.0 - 1; - i = T.1; - i.0 = i; - if (i.0 == 0) - iftmp.2 = 1; - else - iftmp.2 = 0; - j = iftmp.2; - @{ - int x; - - x = 42; - goto test; - loop:; - - T.3 = g (); - T.4 = T.3 * 4; - i.0 = i; - T.5 = T.4 + i.0; - T.6 = T.5 + 32; - i = T.6; - x = x - 1; - - test:; - if (x > 0) - goto loop; - else - goto break_; - break_:; - @} - @} - finally - @{ - __comp_dtor (&a); - @} - @} -@} -@end smallexample - -@node Rough GIMPLE Grammar -@subsection Rough GIMPLE Grammar -@cindex Rough GIMPLE Grammar - -@smallexample - function : FUNCTION_DECL - DECL_SAVED_TREE -> compound-stmt - - compound-stmt: STATEMENT_LIST - members -> stmt - - stmt : block - | if-stmt - | switch-stmt - | goto-stmt - | return-stmt - | resx-stmt - | label-stmt - | try-stmt - | modify-stmt - | call-stmt - - block : BIND_EXPR - BIND_EXPR_VARS -> chain of DECLs - BIND_EXPR_BLOCK -> BLOCK - BIND_EXPR_BODY -> compound-stmt - - if-stmt : COND_EXPR - op0 -> condition - op1 -> compound-stmt - op2 -> compound-stmt - - switch-stmt : SWITCH_EXPR - op0 -> val - op1 -> NULL - op2 -> TREE_VEC of CASE_LABEL_EXPRs - The CASE_LABEL_EXPRs are sorted by CASE_LOW, - and default is last. - - goto-stmt : GOTO_EXPR - op0 -> LABEL_DECL | val - - return-stmt : RETURN_EXPR - op0 -> return-value - - return-value : NULL - | RESULT_DECL - | MODIFY_EXPR - op0 -> RESULT_DECL - op1 -> lhs - - resx-stmt : RESX_EXPR - - label-stmt : LABEL_EXPR - op0 -> LABEL_DECL - - try-stmt : TRY_CATCH_EXPR - op0 -> compound-stmt - op1 -> handler - | TRY_FINALLY_EXPR - op0 -> compound-stmt - op1 -> compound-stmt - - handler : catch-seq - | EH_FILTER_EXPR - | compound-stmt - - catch-seq : STATEMENT_LIST - members -> CATCH_EXPR - - modify-stmt : MODIFY_EXPR - op0 -> lhs - op1 -> rhs - - call-stmt : CALL_EXPR - op0 -> val | OBJ_TYPE_REF - op1 -> call-arg-list - - call-arg-list: TREE_LIST - members -> lhs | CONST - - addr-expr-arg: ID - | compref - - addressable : addr-expr-arg - | indirectref - - with-size-arg: addressable - | call-stmt - - indirectref : INDIRECT_REF - op0 -> val - - lhs : addressable - | bitfieldref - | WITH_SIZE_EXPR - op0 -> with-size-arg - op1 -> val - - min-lval : ID - | indirectref - - bitfieldref : BIT_FIELD_REF - op0 -> inner-compref - op1 -> CONST - op2 -> val - - compref : inner-compref - | TARGET_MEM_REF - op0 -> ID - op1 -> val - op2 -> val - op3 -> CONST - op4 -> CONST - | REALPART_EXPR - op0 -> inner-compref - | IMAGPART_EXPR - op0 -> inner-compref - - inner-compref: min-lval - | COMPONENT_REF - op0 -> inner-compref - op1 -> FIELD_DECL - op2 -> val - | ARRAY_REF - op0 -> inner-compref - op1 -> val - op2 -> val - op3 -> val - | ARRAY_RANGE_REF - op0 -> inner-compref - op1 -> val - op2 -> val - op3 -> val - | VIEW_CONVERT_EXPR - op0 -> inner-compref - - condition : val - | RELOP - op0 -> val - op1 -> val - - val : ID - | invariant ADDR_EXPR - op0 -> addr-expr-arg - | CONST - - rhs : lhs - | CONST - | call-stmt - | ADDR_EXPR - op0 -> addr-expr-arg - | UNOP - op0 -> val - | BINOP - op0 -> val - op1 -> val - | RELOP - op0 -> val - op1 -> val - | COND_EXPR - op0 -> condition - op1 -> val - op2 -> val -@end smallexample - @node Annotations @section Annotations @cindex annotations -The optimizers need to associate attributes with statements and -variables during the optimization process. For instance, we need to -know what basic block a statement belongs to or whether a variable -has aliases. All these attributes are stored in data structures -called annotations which are then linked to the field @code{ann} in -@code{struct tree_common}. +The optimizers need to associate attributes with variables during the +optimization process. For instance, we need to know whether a +variable has aliases. All these attributes are stored in data +structures called annotations which are then linked to the field +@code{ann} in @code{struct tree_common}. -Presently, we define annotations for statements (@code{stmt_ann_t}), -variables (@code{var_ann_t}) and SSA names (@code{ssa_name_ann_t}). +Presently, we define annotations for variables (@code{var_ann_t}). Annotations are defined and documented in @file{tree-flow.h}. -@node Statement Operands -@section Statement Operands +@node SSA Operands +@section SSA Operands @cindex operands @cindex virtual operands @cindex real operands diff --git a/gcc/final.c b/gcc/final.c index a9b51caeeca..e2d9e5a9766 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -3349,6 +3349,31 @@ output_asm_label (rtx x) assemble_name (asm_out_file, buf); } +/* Helper rtx-iteration-function for output_operand. Marks + SYMBOL_REFs as referenced through use of assemble_external. */ + +static int +mark_symbol_ref_as_used (rtx *xp, void *dummy ATTRIBUTE_UNUSED) +{ + rtx x = *xp; + + /* If we have a used symbol, we may have to emit assembly + annotations corresponding to whether the symbol is external, weak + or has non-default visibility. */ + if (GET_CODE (x) == SYMBOL_REF) + { + tree t; + + t = SYMBOL_REF_DECL (x); + if (t) + assemble_external (t); + + return -1; + } + + return 0; +} + /* Print operand X using machine-dependent assembler syntax. The macro PRINT_OPERAND is defined just to control this function. CODE is a non-digit that preceded the operand-number in the % spec, @@ -3369,14 +3394,11 @@ output_operand (rtx x, int code ATTRIBUTE_UNUSED) gcc_assert (!x || !REG_P (x) || REGNO (x) < FIRST_PSEUDO_REGISTER); PRINT_OPERAND (asm_out_file, x, code); - if (x && MEM_P (x) && GET_CODE (XEXP (x, 0)) == SYMBOL_REF) - { - tree t; - x = XEXP (x, 0); - t = SYMBOL_REF_DECL (x); - if (t) - assemble_external (t); - } + + if (x == NULL_RTX) + return; + + for_each_rtx (&x, mark_symbol_ref_as_used, NULL); } /* Print a memory reference operand for address X diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index c972097a67b..e3624139157 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,34 @@ +2008-09-21 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/37583 + * decl.c (scalarize_intrinsic_call): Both subroutines and + functions can give a true for get_proc_mame's last argument so + remove the &&gfc_current_ns->proc_name->attr.function. + resolve.c (resolve_actual_arglist): Add check for recursion by + reference to procedure as actual argument. + +2008-09-21 Daniel Kraft <d@domob.eu> + + PR fortran/35846 + * trans.h (gfc_conv_string_length): New argument `expr'. + * trans-expr.c (flatten_array_ctors_without_strlen): New method. + (gfc_conv_string_length): New argument `expr' that is used in a new + special case handling if cl->length is NULL. + (gfc_conv_subref_array_arg): Pass expr to gfc_conv_string_length. + * trans-array.c (gfc_conv_expr_descriptor): Ditto. + (gfc_trans_auto_array_allocation): Pass NULL as new expr. + (gfc_trans_g77_array), (gfc_trans_dummy_array_bias): Ditto. + (gfc_trans_deferred_array): Ditto. + (gfc_trans_array_constructor): Save and restore old values of globals + used for bounds checking. + * trans-decl.c (gfc_trans_dummy_character): Ditto. + (gfc_trans_auto_character_variable): Ditto. + +2008-09-21 Daniel Kraft <d@domob.eu> + + * decl.c (match_procedure_in_type): Changed misleading error message + for not yet implemented PROCEDURE(interface) syntax. + 2008-09-18 Paul Thomas <pault@gcc.gnu.org> PR fortran/35945 diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c index 7e4cabf21ad..370ac10b3a9 100644 --- a/gcc/fortran/decl.c +++ b/gcc/fortran/decl.c @@ -4639,8 +4639,7 @@ gfc_match_entry (void) created symbols attached to the current namespace. */ if (get_proc_name (name, &entry, gfc_current_ns->parent != NULL - && module_procedure - && gfc_current_ns->proc_name->attr.function)) + && module_procedure)) return MATCH_ERROR; proc = gfc_current_block (); @@ -6907,8 +6906,7 @@ match_procedure_in_type (void) /* TODO: Really implement PROCEDURE(interface). */ if (gfc_match (" (") == MATCH_YES) { - gfc_error ("Procedure with interface only allowed in abstract types at" - " %C"); + gfc_error ("PROCEDURE(interface) at %C is not yet implemented"); return MATCH_ERROR; } diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c index f8f2df972cc..a7c62c30532 100644 --- a/gcc/fortran/resolve.c +++ b/gcc/fortran/resolve.c @@ -1176,6 +1176,15 @@ resolve_actual_arglist (gfc_actual_arglist *arg, procedure_type ptype, /* Just in case a specific was found for the expression. */ sym = e->symtree->n.sym; + if (sym->attr.entry && sym->ns->entries + && sym->ns == gfc_current_ns + && !sym->ns->entries->sym->attr.recursive) + { + gfc_error ("Reference to ENTRY '%s' at %L is recursive, but procedure " + "'%s' is not declared as RECURSIVE", + sym->name, &e->where, sym->ns->entries->sym->name); + } + /* If the symbol is the function that names the current (or parent) scope, then we really have a variable reference. */ diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c index f4af4f25da1..42b9967764f 100644 --- a/gcc/fortran/trans-array.c +++ b/gcc/fortran/trans-array.c @@ -1694,6 +1694,13 @@ gfc_trans_array_constructor (gfc_loopinfo * loop, gfc_ss * ss, locus * where) tree type; tree loopfrom; bool dynamic; + bool old_first_len, old_typespec_chararray_ctor; + tree old_first_len_val; + + /* Save the old values for nested checking. */ + old_first_len = first_len; + old_first_len_val = first_len_val; + old_typespec_chararray_ctor = typespec_chararray_ctor; /* Do bounds-checking here and in gfc_trans_array_ctor_element only if no typespec was given for the array constructor. */ @@ -1792,7 +1799,7 @@ gfc_trans_array_constructor (gfc_loopinfo * loop, gfc_ss * ss, locus * where) if (size && compare_tree_int (size, nelem) == 0) { gfc_trans_constant_array_constructor (loop, ss, type); - return; + goto finish; } } } @@ -1849,6 +1856,12 @@ gfc_trans_array_constructor (gfc_loopinfo * loop, gfc_ss * ss, locus * where) gcc_unreachable (); } #endif + +finish: + /* Restore old values of globals. */ + first_len = old_first_len; + first_len_val = old_first_len_val; + typespec_chararray_ctor = old_typespec_chararray_ctor; } @@ -4080,7 +4093,7 @@ gfc_trans_auto_array_allocation (tree decl, gfc_symbol * sym, tree fnbody) if (sym->ts.type == BT_CHARACTER && onstack && !INTEGER_CST_P (sym->ts.cl->backend_decl)) { - gfc_conv_string_length (sym->ts.cl, &block); + gfc_conv_string_length (sym->ts.cl, NULL, &block); gfc_trans_vla_type_sizes (sym, &block); @@ -4104,7 +4117,7 @@ gfc_trans_auto_array_allocation (tree decl, gfc_symbol * sym, tree fnbody) if (sym->ts.type == BT_CHARACTER && !INTEGER_CST_P (sym->ts.cl->backend_decl)) - gfc_conv_string_length (sym->ts.cl, &block); + gfc_conv_string_length (sym->ts.cl, NULL, &block); size = gfc_trans_array_bounds (type, sym, &offset, &block); @@ -4170,7 +4183,7 @@ gfc_trans_g77_array (gfc_symbol * sym, tree body) if (sym->ts.type == BT_CHARACTER && TREE_CODE (sym->ts.cl->backend_decl) == VAR_DECL) - gfc_conv_string_length (sym->ts.cl, &block); + gfc_conv_string_length (sym->ts.cl, NULL, &block); /* Evaluate the bounds of the array. */ gfc_trans_array_bounds (type, sym, &offset, &block); @@ -4262,7 +4275,7 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc, tree body) if (sym->ts.type == BT_CHARACTER && TREE_CODE (sym->ts.cl->backend_decl) == VAR_DECL) - gfc_conv_string_length (sym->ts.cl, &block); + gfc_conv_string_length (sym->ts.cl, NULL, &block); checkparm = (sym->as->type == AS_EXPLICIT && flag_bounds_check); @@ -4848,7 +4861,6 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss) break; } - gfc_init_loopinfo (&loop); /* Associate the SS with the loop. */ @@ -4872,7 +4884,7 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss) loop.temp_ss->next = gfc_ss_terminator; if (expr->ts.type == BT_CHARACTER && !expr->ts.cl->backend_decl) - gfc_conv_string_length (expr->ts.cl, &se->pre); + gfc_conv_string_length (expr->ts.cl, expr, &se->pre); loop.temp_ss->data.temp.type = gfc_typenode_for_spec (&expr->ts); @@ -5672,7 +5684,7 @@ gfc_trans_deferred_array (gfc_symbol * sym, tree body) if (sym->ts.type == BT_CHARACTER && !INTEGER_CST_P (sym->ts.cl->backend_decl)) { - gfc_conv_string_length (sym->ts.cl, &fnblock); + gfc_conv_string_length (sym->ts.cl, NULL, &fnblock); gfc_trans_vla_type_sizes (sym, &fnblock); } diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c index ec00ee2ee8f..20253e668ca 100644 --- a/gcc/fortran/trans-decl.c +++ b/gcc/fortran/trans-decl.c @@ -2583,7 +2583,7 @@ gfc_trans_dummy_character (gfc_symbol *sym, gfc_charlen *cl, tree fnbody) gfc_start_block (&body); /* Evaluate the string length expression. */ - gfc_conv_string_length (cl, &body); + gfc_conv_string_length (cl, NULL, &body); gfc_trans_vla_type_sizes (sym, &body); @@ -2607,7 +2607,7 @@ gfc_trans_auto_character_variable (gfc_symbol * sym, tree fnbody) gfc_start_block (&body); /* Evaluate the string length expression. */ - gfc_conv_string_length (sym->ts.cl, &body); + gfc_conv_string_length (sym->ts.cl, NULL, &body); gfc_trans_vla_type_sizes (sym, &body); diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c index 216b3df1c96..e0f2f77cd59 100644 --- a/gcc/fortran/trans-expr.c +++ b/gcc/fortran/trans-expr.c @@ -241,17 +241,102 @@ gfc_get_expr_charlen (gfc_expr *e) return length; } - + +/* For each character array constructor subexpression without a ts.cl->length, + replace it by its first element (if there aren't any elements, the length + should already be set to zero). */ + +static void +flatten_array_ctors_without_strlen (gfc_expr* e) +{ + gfc_actual_arglist* arg; + gfc_constructor* c; + + if (!e) + return; + + switch (e->expr_type) + { + + case EXPR_OP: + flatten_array_ctors_without_strlen (e->value.op.op1); + flatten_array_ctors_without_strlen (e->value.op.op2); + break; + + case EXPR_COMPCALL: + /* TODO: Implement as with EXPR_FUNCTION when needed. */ + gcc_unreachable (); + + case EXPR_FUNCTION: + for (arg = e->value.function.actual; arg; arg = arg->next) + flatten_array_ctors_without_strlen (arg->expr); + break; + + case EXPR_ARRAY: + + /* We've found what we're looking for. */ + if (e->ts.type == BT_CHARACTER && !e->ts.cl->length) + { + gfc_expr* new_expr; + gcc_assert (e->value.constructor); + + new_expr = e->value.constructor->expr; + e->value.constructor->expr = NULL; + + flatten_array_ctors_without_strlen (new_expr); + gfc_replace_expr (e, new_expr); + break; + } + + /* Otherwise, fall through to handle constructor elements. */ + case EXPR_STRUCTURE: + for (c = e->value.constructor; c; c = c->next) + flatten_array_ctors_without_strlen (c->expr); + break; + + default: + break; + + } +} + /* Generate code to initialize a string length variable. Returns the - value. */ + value. For array constructors, cl->length might be NULL and in this case, + the first element of the constructor is needed. expr is the original + expression so we can access it but can be NULL if this is not needed. */ void -gfc_conv_string_length (gfc_charlen * cl, stmtblock_t * pblock) +gfc_conv_string_length (gfc_charlen * cl, gfc_expr * expr, stmtblock_t * pblock) { gfc_se se; gfc_init_se (&se, NULL); + + /* If cl->length is NULL, use gfc_conv_expr to obtain the string length but + "flatten" array constructors by taking their first element; all elements + should be the same length or a cl->length should be present. */ + if (!cl->length) + { + gfc_expr* expr_flat; + gcc_assert (expr); + + expr_flat = gfc_copy_expr (expr); + flatten_array_ctors_without_strlen (expr_flat); + gfc_resolve_expr (expr_flat); + + gfc_conv_expr (&se, expr_flat); + gfc_add_block_to_block (pblock, &se.pre); + cl->backend_decl = convert (gfc_charlen_type_node, se.string_length); + + gfc_free_expr (expr_flat); + return; + } + + /* Convert cl->length. */ + + gcc_assert (cl->length); + gfc_conv_expr_type (&se, cl->length, gfc_charlen_type_node); se.expr = fold_build2 (MAX_EXPR, gfc_charlen_type_node, se.expr, build_int_cst (gfc_charlen_type_node, 0)); @@ -2092,7 +2177,7 @@ gfc_conv_subref_array_arg (gfc_se * parmse, gfc_expr * expr, /* Build an ss for the temporary. */ if (expr->ts.type == BT_CHARACTER && !expr->ts.cl->backend_decl) - gfc_conv_string_length (expr->ts.cl, &parmse->pre); + gfc_conv_string_length (expr->ts.cl, expr, &parmse->pre); base_type = gfc_typenode_for_spec (&expr->ts); if (GFC_ARRAY_TYPE_P (base_type) diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h index 36553ea255b..b3a0368160f 100644 --- a/gcc/fortran/trans.h +++ b/gcc/fortran/trans.h @@ -340,7 +340,7 @@ tree gfc_conv_string_tmp (gfc_se *, tree, tree); /* Get the string length variable belonging to an expression. */ tree gfc_get_expr_charlen (gfc_expr *); /* Initialize a string length variable. */ -void gfc_conv_string_length (gfc_charlen *, stmtblock_t *); +void gfc_conv_string_length (gfc_charlen *, gfc_expr *, stmtblock_t *); /* Ensure type sizes can be gimplified. */ void gfc_trans_vla_type_sizes (gfc_symbol *, stmtblock_t *); diff --git a/gcc/gimple.c b/gcc/gimple.c index 9075b2e58e2..f6a14505658 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -3188,9 +3188,11 @@ canonicalize_cond_expr_cond (tree t) return NULL_TREE; } -/* Build call same as STMT but skipping arguments ARGS_TO_SKIP. */ +/* Build a GIMPLE_CALL identical to STMT but skipping the arguments in + the positions marked by the set ARGS_TO_SKIP. */ + gimple -giple_copy_call_skip_args (gimple stmt, bitmap args_to_skip) +gimple_copy_call_skip_args (gimple stmt, bitmap args_to_skip) { int i; tree fn = gimple_call_fn (stmt); diff --git a/gcc/gimple.h b/gcc/gimple.h index 03b6217ebab..85fc75e0a52 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -4479,7 +4479,7 @@ basic_block gsi_insert_on_edge_immediate (edge, gimple); basic_block gsi_insert_seq_on_edge_immediate (edge, gimple_seq); void gsi_commit_one_edge_insert (edge, basic_block *); void gsi_commit_edge_inserts (void); -gimple giple_copy_call_skip_args (gimple, bitmap); +gimple gimple_copy_call_skip_args (gimple, bitmap); /* Convenience routines to walk all statements of a gimple function. diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index 455ba91ec35..46981972f16 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -967,7 +967,8 @@ ipcp_update_callgraph (void) current_function_decl = cs->caller->decl; push_cfun (DECL_STRUCT_FUNCTION (cs->caller->decl)); - new_stmt = giple_copy_call_skip_args (cs->call_stmt, args_to_skip); + new_stmt = gimple_copy_call_skip_args (cs->call_stmt, + args_to_skip); gsi = gsi_for_stmt (cs->call_stmt); gsi_replace (&gsi, new_stmt, true); cgraph_set_call_stmt (cs, new_stmt); @@ -1050,7 +1051,7 @@ ipcp_estimate_growth (struct cgraph_node *node) int growth; for (cs = node->callers; cs != NULL; cs = cs->next_caller) - if (!ipcp_need_redirect_p (cs)) + if (cs->caller == node || !ipcp_need_redirect_p (cs)) redirectable_node_callers++; else need_original = true; @@ -1158,7 +1159,6 @@ ipcp_insert_stage (void) int i; VEC (cgraph_edge_p, heap) * redirect_callers; varray_type replace_trees; - struct cgraph_edge *cs; int node_callers, count; tree parm_tree; struct ipa_replace_map *replace_param; @@ -1208,6 +1208,7 @@ ipcp_insert_stage (void) struct ipa_node_params *info; int growth = 0; bitmap args_to_skip; + struct cgraph_edge *cs; node = (struct cgraph_node *)fibheap_extract_min (heap); node->aux = NULL; @@ -1229,6 +1230,13 @@ ipcp_insert_stage (void) new_insns += growth; + /* Look if original function becomes dead after clonning. */ + for (cs = node->callers; cs != NULL; cs = cs->next_caller) + if (cs->caller == node || ipcp_need_redirect_p (cs)) + break; + if (!cs && !node->needed) + bitmap_set_bit (dead_nodes, node->uid); + info = IPA_NODE_REF (node); count = ipa_get_param_count (info); diff --git a/gcc/ira.c b/gcc/ira.c index dfaf34fa4aa..f4d399cb491 100644 --- a/gcc/ira.c +++ b/gcc/ira.c @@ -714,8 +714,6 @@ enum reg_class ira_important_classes[N_REG_CLASSES]; classes. */ int ira_important_class_nums[N_REG_CLASSES]; -#ifdef IRA_COVER_CLASSES - /* Check IRA_COVER_CLASSES and sets the four global variables defined above. */ static void @@ -723,9 +721,10 @@ setup_cover_and_important_classes (void) { int i, j; enum reg_class cl; - static enum reg_class classes[] = IRA_COVER_CLASSES; + const enum reg_class *classes; HARD_REG_SET temp_hard_regset2; + classes = targetm.ira_cover_classes (); ira_reg_class_cover_size = 0; for (i = 0; (cl = classes[i]) != LIM_REG_CLASSES; i++) { @@ -761,15 +760,12 @@ setup_cover_and_important_classes (void) } } } -#endif /* Map of all register classes to corresponding cover class containing the given class. If given class is not a subset of a cover class, we translate it into the cheapest cover class. */ enum reg_class ira_class_translate[N_REG_CLASSES]; -#ifdef IRA_COVER_CLASSES - /* Set up array IRA_CLASS_TRANSLATE. */ static void setup_class_translate (void) @@ -837,7 +833,6 @@ setup_class_translate (void) ira_class_translate[cl] = best_class; } } -#endif /* The biggest important reg_class inside of intersection of the two reg_classes (that is calculated taking only hard registers @@ -856,8 +851,6 @@ enum reg_class ira_reg_class_intersect[N_REG_CLASSES][N_REG_CLASSES]; reg_class_subunion value. */ enum reg_class ira_reg_class_union[N_REG_CLASSES][N_REG_CLASSES]; -#ifdef IRA_COVER_CLASSES - /* Set up IRA_REG_CLASS_INTERSECT and IRA_REG_CLASS_UNION. */ static void setup_reg_class_intersect_union (void) @@ -943,8 +936,6 @@ setup_reg_class_intersect_union (void) } } -#endif - /* Output all cover classes and the translation map into file F. */ static void print_class_cover (FILE *f) @@ -975,11 +966,12 @@ static void find_reg_class_closure (void) { setup_reg_subclasses (); -#ifdef IRA_COVER_CLASSES - setup_cover_and_important_classes (); - setup_class_translate (); - setup_reg_class_intersect_union (); -#endif + if (targetm.ira_cover_classes) + { + setup_cover_and_important_classes (); + setup_class_translate (); + setup_reg_class_intersect_union (); + } } diff --git a/gcc/opts.c b/gcc/opts.c index b45c0c53a57..6e210ea7ceb 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -870,10 +870,9 @@ decode_options (unsigned int argc, const char **argv) } } -#ifdef IRA_COVER_CLASSES /* Use IRA if it is implemented for the target. */ - flag_ira = 1; -#endif + if (targetm.ira_cover_classes) + flag_ira = 1; /* -O1 optimizations. */ opt1 = (optimize >= 1); @@ -1097,13 +1096,11 @@ decode_options (unsigned int argc, const char **argv) if (!flag_sel_sched_pipelining) flag_sel_sched_pipelining_outer_loops = 0; -#ifndef IRA_COVER_CLASSES - if (flag_ira) + if (flag_ira && !targetm.ira_cover_classes) { inform (input_location, "-fira does not work on this architecture"); flag_ira = 0; } -#endif /* Save the current optimization options if this is the first call. */ if (first_time_p) diff --git a/gcc/target-def.h b/gcc/target-def.h index 07b7f33a2eb..3a332d88efd 100644 --- a/gcc/target-def.h +++ b/gcc/target-def.h @@ -631,6 +631,12 @@ #define TARGET_HANDLE_PRAGMA_EXTERN_PREFIX 0 #endif +#ifdef IRA_COVER_CLASSES +#define TARGET_IRA_COVER_CLASSES default_ira_cover_classes +#else +#define TARGET_IRA_COVER_CLASSES 0 +#endif + #ifndef TARGET_SECONDARY_RELOAD #define TARGET_SECONDARY_RELOAD default_secondary_reload #endif @@ -907,6 +913,7 @@ TARGET_INVALID_CONVERSION, \ TARGET_INVALID_UNARY_OP, \ TARGET_INVALID_BINARY_OP, \ + TARGET_IRA_COVER_CLASSES, \ TARGET_SECONDARY_RELOAD, \ TARGET_EXPAND_TO_RTL_HOOK, \ TARGET_INSTANTIATE_DECLS, \ diff --git a/gcc/target.h b/gcc/target.h index de8150eb9ba..a7d601ff3ef 100644 --- a/gcc/target.h +++ b/gcc/target.h @@ -899,6 +899,9 @@ struct gcc_target is not permitted on TYPE1 and TYPE2, NULL otherwise. */ const char *(*invalid_binary_op) (int op, const_tree type1, const_tree type2); + /* Return the array of IRA cover classes for the current target. */ + const enum reg_class *(*ira_cover_classes) (void); + /* Return the class for a secondary reload, and fill in extra information. */ enum reg_class (*secondary_reload) (bool, rtx, enum reg_class, enum machine_mode, diff --git a/gcc/targhooks.c b/gcc/targhooks.c index 8edfcfce846..2ea438be336 100644 --- a/gcc/targhooks.c +++ b/gcc/targhooks.c @@ -575,6 +575,15 @@ default_internal_arg_pointer (void) return virtual_incoming_args_rtx; } +#ifdef IRA_COVER_CLASSES +const enum reg_class * +default_ira_cover_classes (void) +{ + static enum reg_class classes[] = IRA_COVER_CLASSES; + return classes; +} +#endif + enum reg_class default_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED, enum reg_class reload_class ATTRIBUTE_UNUSED, diff --git a/gcc/targhooks.h b/gcc/targhooks.h index f8d75e881c8..f5a7a248369 100644 --- a/gcc/targhooks.h +++ b/gcc/targhooks.h @@ -88,6 +88,9 @@ extern const char *hook_invalid_arg_for_unprototyped_fn extern bool hook_bool_const_rtx_commutative_p (const_rtx, int); extern rtx default_function_value (const_tree, const_tree, bool); extern rtx default_internal_arg_pointer (void); +#ifdef IRA_COVER_CLASSES +extern const enum reg_class *default_ira_cover_classes (void); +#endif extern enum reg_class default_secondary_reload (bool, rtx, enum reg_class, enum machine_mode, secondary_reload_info *); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 247d214cb47..ca0e70872a9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,53 @@ +2008-09-22 Hans-Peter Nilsson <hp@axis.com> + + PR middle-end/37170 + PR middle-end/37280 + * gcc.dg/weak/weak-15.c, gcc.dg/weak/weak-16.c, + g++.dg/ext/inline1.C: New tests. + +2008-09-21 Kaz Kojima <kkojima@gcc.gnu.org> + + PR rtl-optimization/33642 + * gcc.c-torture/compile/pr11832.c: XFAIL on sh*-*-*. + * gcc.c-torture/compile/pr33009.c: Likewise. + +2008-09-21 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/37583 + * gfortran.dg/entry_18.f90: New test. + +2008-09-21 Daniel Kraft <d@domob.eu> + + PR fortran/35846 + * gfortran.dg/nested_array_constructor_1.f90: New test. + * gfortran.dg/nested_array_constructor_2.f90: New test. + * gfortran.dg/nested_array_constructor_3.f90: New test. + * gfortran.dg/nested_array_constructor_4.f90: New test. + * gfortran.dg/nested_array_constructor_5.f90: New test. + * gfortran.dg/nested_array_constructor_6.f90: New test. + +2008-09-21 Daniel Kraft <d@domob.eu> + + * gfortran.dg/typebound_proc_4.f03: Changed expected error for not + yet implemented PROCEDURE(interface). + +2008-09-21 Ira Rosen <irar@il.ibm.com> + + PR tree-optimization/37539 + * gcc.dg/vect/pr37539.c: New test. + +2008-09-20 Eric Botcazou <ebotcazou@adacore.com> + + PR rtl-optimization/33642 + * gcc.c-torture/compile/pr11832.c: XFAIL on SPARC. + * gcc.c-torture/compile/pr33009.c: Likewise. + +2008-09-19 Andrew Pinski <andrew_pinski@playstation.sony.com> + + PR tree-opt/30930 + * gcc.dg/tree-ssa/vector-2.c: New test. + * gcc.dg/tree-ssa/vector-3.c: New test. + 2008-09-18 Bob Wilson <bob.wilson@acm.org> * gcc.c-torture/compile/pr11832.c: xfail on xtensa*-*-*. @@ -2695,7 +2745,7 @@ * gfortran.dg/cshift_char_3.f90: New test case. * gfortran.dg/cshift_nan_1.f90: New test case. -2008-08-14 Rafael Ávila de Espíndola <espindola@google.com> +2008-08-14 Rafael Ãvila de EspÃndola <espindola@google.com> * gcc.dg/visibility-14.c: New test. * gcc.dg/visibility-15.c: New test. @@ -3417,7 +3467,7 @@ PR tree-optimization/36967 * gfortran.dg/pr36967.f: New testcase. -2008-07-30 Rafael Ávila de Espíndola <espindola@google.com> +2008-07-30 Rafael Ãvila de EspÃndola <espindola@google.com> * gcc.dg/visibility-14.c: New test. * gcc.dg/visibility-15.c: New test. @@ -5111,7 +5161,7 @@ dg-additional-sources. (profopt-execute): Handle additional sources. -2008-05-28 Rafael Espíndola <espindola@google.com> +2008-05-28 Rafael EspÃndola <espindola@google.com> * gcc.dg/20080528-1.c: New test. @@ -5248,7 +5298,7 @@ * g++.dg/template/inline1.C: For the not-defined symbol, use the pattern from g++.dg/template/qualttp17.C. -2008-05-23 Rafael Espíndola <espindola@google.com> +2008-05-23 Rafael EspÃndola <espindola@google.com> * gcc.c-torture/compile/20080522-1.c: Move to gcc.dg. * gcc.dg/20080522-1.c: Moved from gcc.c-torture. @@ -5286,7 +5336,7 @@ * gfortran.dg/cshift_large_1.f90: New test. * gfortran.dg/eoshift_large_1.f90: New test. -2008-05-22 Rafael Espíndola <espindola@google.com> +2008-05-22 Rafael EspÃndola <espindola@google.com> * gcc.c-torture/compile/20080522-1.c: New testcase. @@ -6051,7 +6101,7 @@ PR fortran/36162 * gfortran.dg/module_widestring_1.f90: New test. -2008-05-08 Rafael Espíndola <espindola@google.com> +2008-05-08 Rafael EspÃndola <espindola@google.com> * gcc.dg/vect/vect-111.c: Rename to no-trapping-math-vect-111.c * gcc.dg/vect/vect-ifcvt-11.c: Rename to no-trapping-math-vect-ifcvt-11.c @@ -6990,7 +7040,7 @@ PR fortran/35780 * gfortran.dg/simplify_argN_1.f90: New test. -2008-04-06 Tobias Schlüter <tobi@gcc.gnu.org> +2008-04-06 Tobias Schlüter <tobi@gcc.gnu.org> PR fortran/35832 * gfortran.dg/io_constraints_2.f90: Adapt to new error message. @@ -8751,7 +8801,7 @@ * g++.dg/torture/pr35164-1.C: New testcase. * g++.dg/torture/pr35164-2.C: Likewise. -2008-02-15 Dominique d'Humières <dominiq@lps.ens.fr> +2008-02-15 Dominique d'Humières <dominiq@lps.ens.fr> PR testsuite/35119 * g++.dg/template/spec35.C: Change the regular expressions diff --git a/gcc/testsuite/g++.dg/ext/inline1.C b/gcc/testsuite/g++.dg/ext/inline1.C new file mode 100644 index 00000000000..7e5f062e058 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/inline1.C @@ -0,0 +1,34 @@ +// { dg-do compile } +// { dg-options "-O" } +// Make sure inlined non-outlined functions aren't marked weak. +// We'd get a ".weak xyzzy" annotation trigged by the second declaration. + +// { dg-final { scan-assembler-not "weak\[^ \t\]*\[ \t\]_?xyzzy" } } + +// The next check isn't really part of the actual test, just to make +// sure there's no outline-copy of xyzzy, because if that really +// happened, it *should* be marked linkonce or perhaps weak. +// { dg-final { scan-assembler-not "xyzzy" } } + +extern int x; +extern void foo(void); +extern void bar(void); + +extern "C" inline int xyzzy(int a) +{ + foo(); + return a + x; +} + +extern "C" int xyzzy(int); + +extern inline int plugh(int c) +{ + return xyzzy (c); +} + +int y; +void doit(int b) +{ + y = xyzzy (b) + plugh (b); +} diff --git a/gcc/testsuite/gcc.c-torture/compile/pr11832.c b/gcc/testsuite/gcc.c-torture/compile/pr11832.c index 3be76363299..05bcf0d76f8 100644 --- a/gcc/testsuite/gcc.c-torture/compile/pr11832.c +++ b/gcc/testsuite/gcc.c-torture/compile/pr11832.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ -/* Currently ICEs for IA64, HPPA, MIPS, CRIS, Xtensa and PowerPC; see PR33642. */ -/* { dg-xfail-if "PR33642" { hppa*-*-* mips*-*-* powerpc*-*-linux* cris-*-* crisv32-*-* ia64-*-* xtensa*-*-* } { "*" } { "" } } */ +/* Currently ICEs for IA64, HPPA, MIPS, CRIS, Xtensa, PowerPC, SH and SPARC; see PR33642. */ +/* { dg-xfail-if "PR33642" { hppa*-*-* mips*-*-* powerpc*-*-linux* cris-*-* crisv32-*-* ia64-*-* xtensa*-*-* sh*-*-* sparc*-*-* } { "*" } { "" } } */ /* Currently ICEs for (x86 && ilp32 && pic). */ /* { dg-xfail-if "PR33642/36240" { { i?86-*-* x86_64-*-* } && { ilp32 && { ! nonpic } } } { "*" } { "" } } */ /* { dg-prune-output ".*internal compiler error.*" } diff --git a/gcc/testsuite/gcc.c-torture/compile/pr33009.c b/gcc/testsuite/gcc.c-torture/compile/pr33009.c index a897c36bdd7..38944b2414a 100644 --- a/gcc/testsuite/gcc.c-torture/compile/pr33009.c +++ b/gcc/testsuite/gcc.c-torture/compile/pr33009.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ -/* Currently ICEs for IA64, HPPA, MIPS, CRIS, Xtensa and PowerPC; see PR33642. */ -/* { dg-xfail-if "PR33642" { hppa*-*-* mips*-*-* powerpc*-*-linux* cris-*-* crisv32-*-* ia64-*-* xtensa*-*-* } { "*" } { "" } } */ +/* Currently ICEs for IA64, HPPA, MIPS, CRIS, Xtensa, PowerPC, SH and SPARC; see PR33642. */ +/* { dg-xfail-if "PR33642" { hppa*-*-* mips*-*-* powerpc*-*-linux* cris-*-* crisv32-*-* ia64-*-* xtensa*-*-* sh*-*-* sparc*-*-* } { "*" } { "" } } */ /* Currently ICEs for (x86 && ilp32 && pic). */ /* { dg-xfail-if "PR33642/36240" { { i?86-*-* x86_64-*-* } && { ilp32 && { ! nonpic } } } { "*" } { "" } } */ /* { dg-prune-output ".*internal compiler error.*" } diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vector-2.c b/gcc/testsuite/gcc.dg/tree-ssa/vector-2.c new file mode 100644 index 00000000000..2ce438899a5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vector-2.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-w -O1 -fdump-tree-final_cleanup" } */ + +#define vector __attribute__(( vector_size(16) )) + +float f(vector float a, int b, vector float c) +{ + vector float dd = c*a; + a = (vector float){0,0,0,0}; + c = (vector float){0,0,0,0}; + { + float d = ((float*)&a)[0]; + float d1 = ((float*)&c)[0]; + return d*d1; + } +} + +/* We should be able to optimize this to just "return 0.0;" */ +/* { dg-final { scan-tree-dump-times "BIT_FIELD_REF" 0 "final_cleanup"} } */ +/* { dg-final { scan-tree-dump-times "0.0" 1 "final_cleanup"} } */ + +/* { dg-final { cleanup-tree-dump "final_cleanup" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vector-3.c b/gcc/testsuite/gcc.dg/tree-ssa/vector-3.c new file mode 100644 index 00000000000..332e127ddcc --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vector-3.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-w -O1 -fdump-tree-final_cleanup" } */ + +#define vector __attribute((vector_size(16) )) +vector float a; + +float f(float b) +{ + vector float c = {0, 0, 0, 0}; + vector float d = {0, 0, 0, 0}; + d += c; + return ((float*)&c)[2]; +} + +/* We should be able to optimize this to just "return 0.0;" */ +/* { dg-final { scan-tree-dump-times "BIT_FIELD_REF" 0 "final_cleanup"} } */ +/* { dg-final { scan-tree-dump-times "0.0" 1 "final_cleanup"} } */ + +/* { dg-final { cleanup-tree-dump "final_cleanup" } } */ + diff --git a/gcc/testsuite/gcc.dg/vect/pr37539.c b/gcc/testsuite/gcc.dg/vect/pr37539.c new file mode 100644 index 00000000000..1d569a9986e --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr37539.c @@ -0,0 +1,45 @@ +/* { dg-require-effective-target vect_int } */ + +#include <stdarg.h> +#include "tree-vect.h" + +__attribute__ ((noinline)) void +ayuv2yuyv_ref (int *d, int *src, int n) +{ + char *dest = (char *)d; + int i; + + for(i=0;i<n/2;i++){ + dest[i*4 + 0] = (src[i*2 + 0])>>16; + dest[i*4 + 1] = (src[i*2 + 1])>>8; + dest[i*4 + 2] = (src[i*2 + 0])>>16; + dest[i*4 + 3] = (src[i*2 + 0])>>0; + } + + /* Check results. */ + for(i=0;i<n/2;i++){ + if (dest[i*4 + 0] != (src[i*2 + 0])>>16 + || dest[i*4 + 1] != (src[i*2 + 1])>>8 + || dest[i*4 + 2] != (src[i*2 + 0])>>16 + || dest[i*4 + 3] != (src[i*2 + 0])>>0) + abort(); + } +} + +int main () +{ + int d[256], src[128], i; + + for (i = 0; i < 128; i++) + src[i] = i; + + ayuv2yuyv_ref(d, src, 128); + + return 0; +} + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" { target vect_strided_wide } } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ + + + diff --git a/gcc/testsuite/gcc.dg/weak/weak-15.c b/gcc/testsuite/gcc.dg/weak/weak-15.c new file mode 100644 index 00000000000..2218ca4a746 --- /dev/null +++ b/gcc/testsuite/gcc.dg/weak/weak-15.c @@ -0,0 +1,39 @@ +/* { dg-do compile } */ +/* { dg-require-weak "" } */ +/* { dg-options "-fno-common" } */ + +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?a" } } */ +/* { dg-final { scan-assembler-not "weak\[^ \t\]*\[ \t\]_?b" } } */ +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?c" } } */ +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?d" } } */ + +#pragma weak a +extern char a[]; + +char *user_a(void) +{ + return a+1; +} + +int x; +int extern inline b(int y) +{ + return x+y; +} + +extern int b(int y); + +int user_b(int z) +{ + return b(z); +} + +#pragma weak c +extern int c; + +int *user_c = &c; + +#pragma weak d +extern char d[]; + +char *user_d = &d[1]; diff --git a/gcc/testsuite/gcc.dg/weak/weak-16.c b/gcc/testsuite/gcc.dg/weak/weak-16.c new file mode 100644 index 00000000000..3bcf3885d7d --- /dev/null +++ b/gcc/testsuite/gcc.dg/weak/weak-16.c @@ -0,0 +1,21 @@ +/* From PR37280. */ +/* { dg-do compile } */ +/* { dg-require-weak "" } */ +/* { dg-options "-fno-common -Os" } */ +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?kallsyms_token_index" } } */ +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?kallsyms_token_table" } } */ + +extern int kallsyms_token_index[] __attribute__((weak)); +extern int kallsyms_token_table[] __attribute__((weak)); +void kallsyms_expand_symbol(int *result) +{ + int len = *result; + int *tptr; + while(len) { + tptr = &kallsyms_token_table[ kallsyms_token_index[*result] ]; + len--; + while (*tptr) tptr++; + *tptr = 1; + } + *result = 0; +} diff --git a/gcc/testsuite/gfortran.dg/entry_18.f90 b/gcc/testsuite/gfortran.dg/entry_18.f90 new file mode 100644 index 00000000000..e00aea7d6b8 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/entry_18.f90 @@ -0,0 +1,36 @@ +! { dg-do compile } +! Test fix for PR37583, in which: +! (i) the reference to glocal prior to the ENTRY caused an internal +! error and +! (ii) the need for a RECURSIVE attribute was ignored. +! +! Contributed by Arjen Markus <arjen.markus@wldelft.nl> +! +module gsub +contains +recursive subroutine suba( g ) ! prefix with "RECURSIVE" + interface + real function g(x) + real x + end function + end interface + real :: x, y + call mysub( glocala ) + return +entry glocala( x, y ) + y = x +end subroutine +subroutine subb( g ) + interface + real function g(x) + real x + end function + end interface + real :: x, y + call mysub( glocalb ) ! { dg-error "is recursive" } + return +entry glocalb( x, y ) + y = x +end subroutine +end module +! { dg-final { cleanup-modules "gsub" } } diff --git a/gcc/testsuite/gfortran.dg/nested_array_constructor_1.f90 b/gcc/testsuite/gfortran.dg/nested_array_constructor_1.f90 new file mode 100644 index 00000000000..54417a0dedd --- /dev/null +++ b/gcc/testsuite/gfortran.dg/nested_array_constructor_1.f90 @@ -0,0 +1,19 @@ +! { dg-do compile } +! This test is run with result-checking and -fbounds-check as +! nested_array_constructor_2.f90 + +! PR fortran/35846 +! This used to ICE because the charlength of the trim-expression was +! NULL. + +! Contributed by Tobias Burnus <burnus@gcc.gnu.org> + +implicit none +character(len=2) :: c(3) + +c = 'a' +c = (/ (/ trim(c(1)), 'a' /)//'c', 'cd' /) + +print *, c + +end diff --git a/gcc/testsuite/gfortran.dg/nested_array_constructor_2.f90 b/gcc/testsuite/gfortran.dg/nested_array_constructor_2.f90 new file mode 100644 index 00000000000..28c2b49e816 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/nested_array_constructor_2.f90 @@ -0,0 +1,22 @@ +! { dg-do run } +! { dg-options "-fbounds-check" } + +! PR fortran/35846 +! This used to ICE because the charlength of the trim-expression was +! NULL. + +! Contributed by Tobias Burnus <burnus@gcc.gnu.org> + +implicit none +character(len=2) :: c(3) + +c = 'a' +c = (/ (/ trim(c(1)), 'a' /)//'c', 'cd' /) + +print *, c + +if (c(1) /= 'ac' .or. c(2) /= 'ac' .or. c(3) /= 'cd') then + call abort () +end if + +end diff --git a/gcc/testsuite/gfortran.dg/nested_array_constructor_3.f90 b/gcc/testsuite/gfortran.dg/nested_array_constructor_3.f90 new file mode 100644 index 00000000000..dd10e5fafc9 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/nested_array_constructor_3.f90 @@ -0,0 +1,22 @@ +! { dg-do run } + +! PR fortran/35846 +! Alternate test that also produced an ICE because of a missing length. + +PROGRAM test + IMPLICIT NONE + CHARACTER(LEN=2) :: x + + x = 'a' + CALL sub ( (/ TRIM(x), 'a' /) // 'c') +END PROGRAM + +SUBROUTINE sub(str) + IMPLICIT NONE + CHARACTER(LEN=*) :: str(2) + WRITE (*,*) str + + IF (str(1) /= 'ac' .OR. str(2) /= 'ac') THEN + CALL abort () + END IF +END SUBROUTINE sub diff --git a/gcc/testsuite/gfortran.dg/nested_array_constructor_4.f90 b/gcc/testsuite/gfortran.dg/nested_array_constructor_4.f90 new file mode 100644 index 00000000000..cb113e9c9ae --- /dev/null +++ b/gcc/testsuite/gfortran.dg/nested_array_constructor_4.f90 @@ -0,0 +1,17 @@ +! { dg-do run } + +! PR fortran/35846 +! Alternate test that also produced an ICE because of a missing length. + +PROGRAM test + IMPLICIT NONE + CHARACTER(LEN=2) :: x + INTEGER :: length + + x = 'a' + length = LEN ( (/ TRIM(x), 'a' /) // 'c') + + IF (length /= 2) THEN + CALL abort () + END IF +END PROGRAM diff --git a/gcc/testsuite/gfortran.dg/nested_array_constructor_5.f90 b/gcc/testsuite/gfortran.dg/nested_array_constructor_5.f90 new file mode 100644 index 00000000000..7744f1ffe94 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/nested_array_constructor_5.f90 @@ -0,0 +1,16 @@ +! { dg-do compile } + +! PR fortran/35846 +! This used to ICE because the charlength of the trim-expression was +! NULL, but it is switched around to test for the right operand of // being +! not a constant, too. + +implicit none +character(len=2) :: c(2) + +c = 'a' +c = (/ (/ trim(c(1)), 'a' /) // (/ trim(c(1)), 'a' /) /) + +print *, c + +end diff --git a/gcc/testsuite/gfortran.dg/nested_array_constructor_6.f90 b/gcc/testsuite/gfortran.dg/nested_array_constructor_6.f90 new file mode 100644 index 00000000000..6eee6d0b32e --- /dev/null +++ b/gcc/testsuite/gfortran.dg/nested_array_constructor_6.f90 @@ -0,0 +1,15 @@ +! { dg-do compile } + +! PR fortran/35846 +! Nested three levels deep. + +! Contributed by Tobias Burnus <burnus@gcc.gnu.org> + +implicit none +character(len=3) :: c(3) +c = 'a' +c = (/ (/ 'A'//(/ trim(c(1)), 'a' /)/)//'c', 'dcd' /) +print *, c(1) +print *, c(2) +print *, c(3) +end diff --git a/gcc/testsuite/gfortran.dg/typebound_proc_4.f03 b/gcc/testsuite/gfortran.dg/typebound_proc_4.f03 index bf5be562776..3eb9687ad02 100644 --- a/gcc/testsuite/gfortran.dg/typebound_proc_4.f03 +++ b/gcc/testsuite/gfortran.dg/typebound_proc_4.f03 @@ -33,7 +33,7 @@ MODULE testmod ! TODO: Correct these when things get implemented. PROCEDURE, DEFERRED :: x ! { dg-error "not yet implemented" } - PROCEDURE(abc) ! { dg-error "abstract type" } + PROCEDURE(abc) ! { dg-error "not yet implemented" } END TYPE t CONTAINS diff --git a/gcc/tree-ssa-ter.c b/gcc/tree-ssa-ter.c index 099c19742e4..cb393fba32b 100644 --- a/gcc/tree-ssa-ter.c +++ b/gcc/tree-ssa-ter.c @@ -220,22 +220,22 @@ static gimple * free_temp_expr_table (temp_expr_table_p t) { gimple *ret = NULL; - unsigned i; #ifdef ENABLE_CHECKING unsigned x; for (x = 0; x <= num_var_partitions (t->map); x++) gcc_assert (!t->kill_list[x]); + for (x = 0; x < num_ssa_names + 1; x++) + { + gcc_assert (t->expr_decl_uids[x] == NULL); + gcc_assert (t->partition_dependencies[x] == NULL); + } #endif BITMAP_FREE (t->partition_in_use); BITMAP_FREE (t->new_replaceable_dependencies); - for (i = 0; i <= num_ssa_names; i++) - if (t->expr_decl_uids[i]) - BITMAP_FREE (t->expr_decl_uids[i]); free (t->expr_decl_uids); - free (t->kill_list); free (t->partition_dependencies); free (t->num_in_part); @@ -664,27 +664,14 @@ find_replaceable_exprs (var_map map) FOR_EACH_BB (bb) { find_replaceable_in_bb (table, bb); - gcc_assert (bitmap_empty_p (table->partition_in_use)); - #ifdef ENABLE_CHECKING - { - unsigned i; - /* Make sure all the tables have been cleared out. */ - for (i = 0; i < num_ssa_names + 1; i++) - { - gcc_assert (table->partition_dependencies[i] == NULL); - gcc_assert (table->expr_decl_uids[i] == NULL); - if (i < num_var_partitions (map)) - gcc_assert (table->kill_list[i] == NULL); - } - } + gcc_assert (bitmap_empty_p (table->partition_in_use)); #endif } ret = free_temp_expr_table (table); return ret; -} - +} /* Dump TER expression table EXPR to file F. */ diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c index 6a1f6f353c8..073e1290b3c 100644 --- a/gcc/tree-ssa.c +++ b/gcc/tree-ssa.c @@ -1653,7 +1653,7 @@ struct gimple_opt_pass pass_late_warn_uninitialized = } }; -/* Compute TREE_ADDRESSABLE for local variables. */ +/* Compute TREE_ADDRESSABLE and DECL_GIMPLE_REG_P for local variables. */ static unsigned int execute_update_addresses_taken (void) @@ -1663,6 +1663,7 @@ execute_update_addresses_taken (void) gimple_stmt_iterator gsi; basic_block bb; bitmap addresses_taken = BITMAP_ALLOC (NULL); + bitmap not_reg_needs = BITMAP_ALLOC (NULL); bitmap vars_updated = BITMAP_ALLOC (NULL); bool update_vops = false; @@ -1672,9 +1673,26 @@ execute_update_addresses_taken (void) { for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) { - bitmap taken = gimple_addresses_taken (gsi_stmt (gsi)); + const_gimple stmt = gsi_stmt (gsi); + enum gimple_code code = gimple_code (stmt); + bitmap taken = gimple_addresses_taken (stmt); + if (taken) bitmap_ior_into (addresses_taken, taken); + + /* If we have a call or an assignment, see if the lhs contains + a local decl that requires not to be a gimple register. */ + if (code == GIMPLE_ASSIGN || code == GIMPLE_CALL) + { + tree lhs = gimple_get_lhs (stmt); + /* A plain decl does not need it set. */ + if (lhs && handled_component_p (lhs)) + { + var = get_base_address (lhs); + if (DECL_P (var)) + bitmap_set_bit (not_reg_needs, DECL_UID (var)); + } + } } for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi)) @@ -1693,25 +1711,46 @@ execute_update_addresses_taken (void) } } - /* When possible, clear ADDRESSABLE bit and mark variable for conversion into - SSA. */ + /* When possible, clear ADDRESSABLE bit or set the REGISTER bit + and mark variable for conversion into SSA. */ FOR_EACH_REFERENCED_VAR (var, rvi) - if (!is_global_var (var) - && TREE_CODE (var) != RESULT_DECL - && TREE_ADDRESSABLE (var) - && !bitmap_bit_p (addresses_taken, DECL_UID (var))) - { - TREE_ADDRESSABLE (var) = 0; - if (is_gimple_reg (var)) + { + /* Global Variables, result decls cannot be changed. */ + if (is_global_var (var) + || TREE_CODE (var) == RESULT_DECL + || bitmap_bit_p (addresses_taken, DECL_UID (var))) + continue; + + if (TREE_ADDRESSABLE (var)) + { + TREE_ADDRESSABLE (var) = 0; + if (is_gimple_reg (var)) + mark_sym_for_renaming (var); + update_vops = true; + bitmap_set_bit (vars_updated, DECL_UID (var)); + if (dump_file) + { + fprintf (dump_file, "No longer having address taken "); + print_generic_expr (dump_file, var, 0); + fprintf (dump_file, "\n"); + } + } + if (!DECL_GIMPLE_REG_P (var) + && !bitmap_bit_p (not_reg_needs, DECL_UID (var)) + && (TREE_CODE (TREE_TYPE (var)) == COMPLEX_TYPE + || TREE_CODE (TREE_TYPE (var)) == VECTOR_TYPE)) + { + DECL_GIMPLE_REG_P (var) = 1; mark_sym_for_renaming (var); - update_vops = true; - bitmap_set_bit (vars_updated, DECL_UID (var)); - if (dump_file) - { - fprintf (dump_file, "No longer having address taken "); - print_generic_expr (dump_file, var, 0); - fprintf (dump_file, "\n"); - } + update_vops = true; + bitmap_set_bit (vars_updated, DECL_UID (var)); + if (dump_file) + { + fprintf (dump_file, "Decl is now a gimple register "); + print_generic_expr (dump_file, var, 0); + fprintf (dump_file, "\n"); + } + } } /* Operand caches needs to be recomputed for operands referencing the updated @@ -1728,6 +1767,7 @@ execute_update_addresses_taken (void) && bitmap_intersect_p (gimple_stored_syms (stmt), vars_updated))) update_stmt (stmt); } + BITMAP_FREE (not_reg_needs); BITMAP_FREE (addresses_taken); BITMAP_FREE (vars_updated); return 0; diff --git a/gcc/tree-vect-transform.c b/gcc/tree-vect-transform.c index 06d6791e639..4965da4ad0c 100644 --- a/gcc/tree-vect-transform.c +++ b/gcc/tree-vect-transform.c @@ -5947,17 +5947,24 @@ vect_transform_strided_load (gimple stmt, VEC(tree,heap) *dr_chain, int size, STMT_VINFO_VEC_STMT (vinfo_for_stmt (next_stmt)) = new_stmt; else { - gimple prev_stmt = - STMT_VINFO_VEC_STMT (vinfo_for_stmt (next_stmt)); - gimple rel_stmt = - STMT_VINFO_RELATED_STMT (vinfo_for_stmt (prev_stmt)); - while (rel_stmt) - { - prev_stmt = rel_stmt; - rel_stmt = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (rel_stmt)); - } - STMT_VINFO_RELATED_STMT (vinfo_for_stmt (prev_stmt)) = new_stmt; + if (!DR_GROUP_SAME_DR_STMT (vinfo_for_stmt (next_stmt))) + { + gimple prev_stmt = + STMT_VINFO_VEC_STMT (vinfo_for_stmt (next_stmt)); + gimple rel_stmt = + STMT_VINFO_RELATED_STMT (vinfo_for_stmt (prev_stmt)); + while (rel_stmt) + { + prev_stmt = rel_stmt; + rel_stmt = + STMT_VINFO_RELATED_STMT (vinfo_for_stmt (rel_stmt)); + } + + STMT_VINFO_RELATED_STMT (vinfo_for_stmt (prev_stmt)) = + new_stmt; + } } + next_stmt = DR_GROUP_NEXT_DR (vinfo_for_stmt (next_stmt)); gap_count = 1; /* If NEXT_STMT accesses the same DR as the previous statement, diff --git a/gcc/varasm.c b/gcc/varasm.c index e74adaed983..4fe3c967032 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -2290,9 +2290,10 @@ process_pending_assemble_externals (void) to be emitted. */ static GTY(()) tree weak_decls; -/* Output something to declare an external symbol to the assembler. - (Most assemblers don't need this, so we normally output nothing.) - Do nothing if DECL is not external. */ +/* Output something to declare an external symbol to the assembler, + and qualifiers such as weakness. (Most assemblers don't need + extern declaration, so we normally output nothing.) Do nothing if + DECL is not external. */ void assemble_external (tree decl ATTRIBUTE_UNUSED) @@ -2303,15 +2304,22 @@ assemble_external (tree decl ATTRIBUTE_UNUSED) open. If it's not, we should not be calling this function. */ gcc_assert (asm_out_file); -#ifdef ASM_OUTPUT_EXTERNAL if (!DECL_P (decl) || !DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl)) return; - if (SUPPORTS_WEAK && DECL_WEAK (decl)) + /* We want to output annotation for weak and external symbols at + very last to check if they are references or not. */ + + if (SUPPORTS_WEAK && DECL_WEAK (decl) + /* TREE_STATIC is a weird and abused creature which is not + generally the right test for whether an entity has been + locally emitted, inlined or otherwise not-really-extern, but + for declarations that can be weak, it happens to be + match. */ + && !TREE_STATIC (decl)) weak_decls = tree_cons (NULL, decl, weak_decls); - /* We want to output external symbols at very last to check if they - are references or not. */ +#ifdef ASM_OUTPUT_EXTERNAL pending_assemble_externals = tree_cons (0, decl, pending_assemble_externals); #endif @@ -4064,9 +4072,10 @@ constructor_static_from_elts_p (const_tree ctor) } /* A subroutine of initializer_constant_valid_p. VALUE is either a - MINUS_EXPR or a POINTER_PLUS_EXPR, and ENDTYPE is a narrowing - conversion to something smaller than a pointer. This returns - null_pointer_node if the resulting value is an absolute constant + MINUS_EXPR or a POINTER_PLUS_EXPR. This looks for cases of VALUE + which are valid when ENDTYPE is an integer of any size; in + particular, this does not accept a pointer minus a constant. This + returns null_pointer_node if the VALUE is an absolute constant which can be used to initialize a static variable. Otherwise it returns NULL. */ @@ -4075,6 +4084,9 @@ narrowing_initializer_constant_valid_p (tree value, tree endtype) { tree op0, op1; + if (!INTEGRAL_TYPE_P (endtype)) + return NULL_TREE; + op0 = TREE_OPERAND (value, 0); op1 = TREE_OPERAND (value, 1); diff --git a/libada/ChangeLog b/libada/ChangeLog index 4f1c8217784..55766736d33 100644 --- a/libada/ChangeLog +++ b/libada/ChangeLog @@ -1,3 +1,12 @@ +2008-09-21 Laurent Guerby <laurent@guerby.net> + Paolo Bonzini <bonzini@gnu.org> + + PR ada/5911 + * Makefile.in (all, install, mostlyclean, clean, distclean): Add + multilib handling. + * configure.ac: Add multilib handling. + * configure: Regenerate. + 2008-08-29 Laurent Guerby <laurent@guerby.net> * Makefile.in (FLAGS_TO_PASS): renamed to LIBADA_FLAGS_TO_PASS to diff --git a/libada/Makefile.in b/libada/Makefile.in index 05a42335f01..2c568688609 100644 --- a/libada/Makefile.in +++ b/libada/Makefile.in @@ -17,6 +17,17 @@ # Default target; must be first. all: gnatlib + $(MULTIDO) $(AM_MAKEFLAGS) DO=all multi-do # $(MAKE) + +.PHONY: all install + +## Multilib support variables. +MULTISRCTOP = +MULTIBUILDTOP = +MULTIDIRS = +MULTISUBDIR = +MULTIDO = true +MULTICLEAN = true # Standard autoconf-set variables. SHELL = @SHELL@ @@ -48,12 +59,12 @@ GNATLIBCFLAGS= -g -O2 # Get target-specific overrides for TARGET_LIBGCC2_CFLAGS. host_subdir = @host_subdir@ -GCC_DIR=../../$(host_subdir)/gcc +GCC_DIR=$(MULTIBUILDTOP)../../$(host_subdir)/gcc include $(GCC_DIR)/libgcc.mvars target_noncanonical:=@target_noncanonical@ version := $(shell cat $(srcdir)/../gcc/BASE-VER) -libsubdir := $(libdir)/gcc/$(target_noncanonical)/$(version) +libsubdir := $(libdir)/gcc/$(target_noncanonical)/$(version)$(MULTISUBDIR) # exeext should not be used because it's the *host* exeext. We're building # a *target* library, aren't we?!? Likewise for CC. Still, provide bogus @@ -64,11 +75,12 @@ LIBADA_FLAGS_TO_PASS = \ "LDFLAGS=$(LDFLAGS)" \ "LN_S=$(LN_S)" \ "SHELL=$(SHELL)" \ - "GNATLIBFLAGS=$(GNATLIBFLAGS)" \ - "GNATLIBCFLAGS=$(GNATLIBCFLAGS)" \ + "GNATLIBFLAGS=$(GNATLIBFLAGS) $(MULTIFLAGS)" \ + "GNATLIBCFLAGS=$(GNATLIBCFLAGS) $(MULTIFLAGS)" \ "TARGET_LIBGCC2_CFLAGS=$(TARGET_LIBGCC2_CFLAGS)" \ "THREAD_KIND=$(THREAD_KIND)" \ "TRACE=$(TRACE)" \ + "MULTISUBDIR=$(MULTISUBDIR)" \ "libsubdir=$(libsubdir)" \ "objext=$(objext)" \ "prefix=$(prefix)" \ @@ -119,7 +131,8 @@ html: TAGS: # Installation rules. -install: +install: install-gnatlib + $(MULTIDO) $(AM_MAKEFLAGS) DO=install multi-do # $(MAKE) install-info: @@ -129,10 +142,13 @@ install-html: # Cleaning rules. mostlyclean: + $(MULTICLEAN) $(AM_MAKEFLAGS) DO=mostlyclean multi-clean # $(MAKE) clean: + $(MULTICLEAN) $(AM_MAKEFLAGS) DO=clean multi-clean # $(MAKE) distclean: + $(MULTICLEAN) $(AM_MAKEFLAGS) DO=distclean multi-clean # $(MAKE) $(RM) Makefile config.status config.log maintainer-clean: diff --git a/libada/configure b/libada/configure index 4364253f75e..56a4b481136 100755 --- a/libada/configure +++ b/libada/configure @@ -272,7 +272,7 @@ PACKAGE_STRING= PACKAGE_BUGREPORT= ac_unique_file="Makefile.in" -ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os target_noncanonical build_libsubdir build_subdir host_subdir target_subdir MAINT enable_shared LN_S default_gnatlib_target CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT warn_cflags LIBOBJS LTLIBOBJS' +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os target_noncanonical build_libsubdir build_subdir host_subdir target_subdir MAINT multi_basedir toolexecdir toolexeclibdir CC ac_ct_CC EXEEXT OBJEXT CFLAGS enable_shared LN_S default_gnatlib_target LDFLAGS CPPFLAGS warn_cflags LIBOBJS LTLIBOBJS' ac_subst_files='' ac_pwd=`pwd` @@ -808,6 +808,7 @@ Optional Features: --enable-maintainer-mode enable make rules and dependencies not useful (and sometimes confusing) to the casual installer + --enable-multilib build many library versions (default) --disable-shared don't provide a shared libgnat Optional Packages: @@ -1456,51 +1457,78 @@ else MAINT='#' fi; -# Check whether --enable-shared or --disable-shared was given. -if test "${enable_shared+set}" = set; then - enableval="$enable_shared" -case $enable_shared in - yes | no) ;; - *) - enable_shared=no - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," - for pkg in $enableval; do - case $pkg in - ada | libada) - enable_shared=yes ;; - esac - done - IFS="$ac_save_ifs" - ;; -esac +target_alias=${target_alias-$host_alias} +# Default to --enable-multilib +# Check whether --enable-multilib or --disable-multilib was given. +if test "${enable_multilib+set}" = set; then + enableval="$enable_multilib" + case "$enableval" in + yes) multilib=yes ;; + no) multilib=no ;; + *) { { echo "$as_me:$LINENO: error: bad value $enableval for multilib option" >&5 +echo "$as_me: error: bad value $enableval for multilib option" >&2;} + { (exit 1); exit 1; }; } ;; + esac else - enable_shared=yes + multilib=yes fi; +# We may get other options which we leave undocumented: +# --with-target-subdir, --with-multisrctop, --with-multisubdir +# See config-ml.in if you want the gory details. -# Need to pass this down for now :-P -echo "$as_me:$LINENO: checking whether ln -s works" >&5 -echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6 -LN_S=$as_ln_s -if test "$LN_S" = "ln -s"; then - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 +if test "$srcdir" = "."; then + if test "$with_target_subdir" != "."; then + multi_basedir="$srcdir/$with_multisrctop../.." + else + multi_basedir="$srcdir/$with_multisrctop.." + fi else - echo "$as_me:$LINENO: result: no, using $LN_S" >&5 -echo "${ECHO_T}no, using $LN_S" >&6 + multi_basedir="$srcdir/.." fi -# Determine what to build for 'gnatlib' -if test $build = $target \ - && test ${enable_shared} = yes ; then - # Note that build=target is almost certainly the wrong test; FIXME - default_gnatlib_target="gnatlib-shared" -else - default_gnatlib_target="gnatlib-plain" -fi + ac_config_commands="$ac_config_commands default-1" + +# Calculate toolexeclibdir +# Also toolexecdir, though it's only used in toolexeclibdir +case ${enable_version_specific_runtime_libs} in + yes) + # Need the gcc compiler version to know where to install libraries + # and header files if --enable-version-specific-runtime-libs option + # is selected. + toolexecdir='$(libdir)/gcc/$(target_alias)' + toolexeclibdir='$(toolexecdir)/$(gcc_version)$(MULTISUBDIR)' + ;; + no) + if test -n "$with_cross_host" && + test x"$with_cross_host" != x"no"; then + # Install a library built with a cross compiler in tooldir, not libdir. + toolexecdir='$(exec_prefix)/$(target_alias)' + toolexeclibdir='$(toolexecdir)/lib' + else + toolexecdir='$(libdir)/gcc-lib/$(target_alias)' + toolexeclibdir='$(libdir)' + fi + multi_os_directory=`$CC -print-multi-os-directory` + case $multi_os_directory in + .) ;; # Avoid trailing /. + *) toolexeclibdir=$toolexeclibdir/$multi_os_directory ;; + esac + ;; +esac + + +#TODO: toolexeclibdir is currently disregarded + +# Check the compiler. +# The same as in boehm-gc and libstdc++. Have to borrow it from there. +# We must force CC to /not/ be precious variables; otherwise +# the wrong, non-multilib-adjusted value will be used in multilibs. +# As a side effect, we have to subst CFLAGS ourselves. + ac_ext=c @@ -2443,6 +2471,788 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + +# Check whether --enable-shared or --disable-shared was given. +if test "${enable_shared+set}" = set; then + enableval="$enable_shared" + +case $enable_shared in + yes | no) ;; + *) + enable_shared=no + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," + for pkg in $enableval; do + case $pkg in + ada | libada) + enable_shared=yes ;; + esac + done + IFS="$ac_save_ifs" + ;; +esac + +else + enable_shared=yes +fi; + + +# Need to pass this down for now :-P +echo "$as_me:$LINENO: checking whether ln -s works" >&5 +echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6 +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +else + echo "$as_me:$LINENO: result: no, using $LN_S" >&5 +echo "${ECHO_T}no, using $LN_S" >&6 +fi + + +# Determine what to build for 'gnatlib' +if test $build = $target \ + && test ${enable_shared} = yes ; then + # Note that build=target is almost certainly the wrong test; FIXME + default_gnatlib_target="gnatlib-shared" +else + default_gnatlib_target="gnatlib-plain" +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CC" && break +done + + CC=$ac_ct_CC +fi + +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 +echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5 + (eval $ac_compiler --version </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5 + (eval $ac_compiler -v </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5 + (eval $ac_compiler -V </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_compiler_gnu=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +CFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_prog_cc_g=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 +echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_prog_cc_stdc=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdarg.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std1 is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std1. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +# Don't try gcc -ansi; that turns off useful extensions and +# breaks some systems' header files. +# AIX -qlanglvl=ansi +# Ultrix and OSF/1 -std1 +# HP-UX 10.20 and later -Ae +# HP-UX older versions -Aa -D_HPUX_SOURCE +# SVR4 -Xc -D__EXTENSIONS__ +for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_stdc=$ac_arg +break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext +done +rm -f conftest.$ac_ext conftest.$ac_objext +CC=$ac_save_CC + +fi + +case "x$ac_cv_prog_cc_stdc" in + x|xno) + echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6 ;; + *) + echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 + CC="$CC $ac_cv_prog_cc_stdc" ;; +esac + +# Some people use a C++ compiler to compile C. Since we use `exit', +# in C++ we need to declare it. In case someone uses the same compiler +# for both compiling C and C++ we need to have the C++ compiler decide +# the declaration of exit, since it's the most demanding environment. +cat >conftest.$ac_ext <<_ACEOF +#ifndef __cplusplus + choke me +#endif +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + for ac_declaration in \ + '' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +#include <stdlib.h> +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +continue +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h +fi + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + warn_cflags= if test "x$GCC" = "xyes"; then warn_cflags='$(GCC_WARN_CFLAGS)' @@ -2896,6 +3706,9 @@ Usage: $0 [OPTIONS] [FILE]... Configuration files: $config_files +Configuration commands: +$config_commands + Report bugs to <bug-autoconf@gnu.org>." _ACEOF @@ -2994,7 +3807,24 @@ fi _ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +# +# INIT-COMMANDS section. +# + + +srcdir="$srcdir" +host="$host" +target="$target" +with_multisubdir="$with_multisubdir" +with_multisrctop="$with_multisrctop" +with_target_subdir="$with_target_subdir" +ac_configure_args="${multilib_arg} ${ac_configure_args}" +multi_basedir="$multi_basedir" +CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} +CC="$CC" +_ACEOF @@ -3004,6 +3834,7 @@ do case "$ac_config_target" in # Handling of arguments. "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "default-1" ) CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 echo "$as_me: error: invalid argument: $ac_config_target" >&2;} { (exit 1); exit 1; }; };; @@ -3016,6 +3847,7 @@ done # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree @@ -3105,16 +3937,19 @@ s,@build_subdir@,$build_subdir,;t t s,@host_subdir@,$host_subdir,;t t s,@target_subdir@,$target_subdir,;t t s,@MAINT@,$MAINT,;t t +s,@multi_basedir@,$multi_basedir,;t t +s,@toolexecdir@,$toolexecdir,;t t +s,@toolexeclibdir@,$toolexeclibdir,;t t +s,@CC@,$CC,;t t +s,@ac_ct_CC@,$ac_ct_CC,;t t +s,@EXEEXT@,$EXEEXT,;t t +s,@OBJEXT@,$OBJEXT,;t t +s,@CFLAGS@,$CFLAGS,;t t s,@enable_shared@,$enable_shared,;t t s,@LN_S@,$LN_S,;t t s,@default_gnatlib_target@,$default_gnatlib_target,;t t -s,@CC@,$CC,;t t -s,@CFLAGS@,$CFLAGS,;t t s,@LDFLAGS@,$LDFLAGS,;t t s,@CPPFLAGS@,$CPPFLAGS,;t t -s,@ac_ct_CC@,$ac_ct_CC,;t t -s,@EXEEXT@,$EXEEXT,;t t -s,@OBJEXT@,$OBJEXT,;t t s,@warn_cflags@,$warn_cflags,;t t s,@LIBOBJS@,$LIBOBJS,;t t s,@LTLIBOBJS@,$LTLIBOBJS,;t t @@ -3351,6 +4186,131 @@ s,@abs_top_builddir@,$ac_abs_top_builddir,;t t done _ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + +# +# CONFIG_COMMANDS section. +# +for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue + ac_dest=`echo "$ac_file" | sed 's,:.*,,'` + ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_dir=`(dirname "$ac_dest") 2>/dev/null || +$as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_dest" : 'X\(//\)[^/]' \| \ + X"$ac_dest" : 'X\(//\)$' \| \ + X"$ac_dest" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_dest" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + + { echo "$as_me:$LINENO: executing $ac_dest commands" >&5 +echo "$as_me: executing $ac_dest commands" >&6;} + case $ac_dest in + default-1 ) +# Only add multilib support code if we just rebuilt the top-level +# Makefile. +case " $CONFIG_FILES " in + *" Makefile "*) + ac_file=Makefile . ${multi_basedir}/config-ml.in + ;; +esac ;; + esac +done +_ACEOF cat >>$CONFIG_STATUS <<\_ACEOF diff --git a/libada/configure.ac b/libada/configure.ac index b0a46d00332..c456e17d00a 100644 --- a/libada/configure.ac +++ b/libada/configure.ac @@ -49,6 +49,54 @@ AC_ARG_ENABLE([maintainer-mode], [MAINT='#']) AC_SUBST([MAINT])dnl +AC_CANONICAL_SYSTEM +target_alias=${target_alias-$host_alias} + +AM_ENABLE_MULTILIB(, ..) +# Calculate toolexeclibdir +# Also toolexecdir, though it's only used in toolexeclibdir +case ${enable_version_specific_runtime_libs} in + yes) + # Need the gcc compiler version to know where to install libraries + # and header files if --enable-version-specific-runtime-libs option + # is selected. + toolexecdir='$(libdir)/gcc/$(target_alias)' + toolexeclibdir='$(toolexecdir)/$(gcc_version)$(MULTISUBDIR)' + ;; + no) + if test -n "$with_cross_host" && + test x"$with_cross_host" != x"no"; then + # Install a library built with a cross compiler in tooldir, not libdir. + toolexecdir='$(exec_prefix)/$(target_alias)' + toolexeclibdir='$(toolexecdir)/lib' + else + toolexecdir='$(libdir)/gcc-lib/$(target_alias)' + toolexeclibdir='$(libdir)' + fi + multi_os_directory=`$CC -print-multi-os-directory` + case $multi_os_directory in + .) ;; # Avoid trailing /. + *) toolexeclibdir=$toolexeclibdir/$multi_os_directory ;; + esac + ;; +esac +AC_SUBST(toolexecdir) +AC_SUBST(toolexeclibdir) +#TODO: toolexeclibdir is currently disregarded + +# Check the compiler. +# The same as in boehm-gc and libstdc++. Have to borrow it from there. +# We must force CC to /not/ be precious variables; otherwise +# the wrong, non-multilib-adjusted value will be used in multilibs. +# As a side effect, we have to subst CFLAGS ourselves. + +m4_rename([_AC_ARG_VAR_PRECIOUS],[real_PRECIOUS]) +m4_define([_AC_ARG_VAR_PRECIOUS],[]) +AC_PROG_CC +m4_rename([real_PRECIOUS],[_AC_ARG_VAR_PRECIOUS]) + +AC_SUBST(CFLAGS) + AC_ARG_ENABLE([shared], [AC_HELP_STRING([--disable-shared], [don't provide a shared libgnat])], diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog index eaa08f9ca30..965bc0416a4 100644 --- a/libgomp/ChangeLog +++ b/libgomp/ChangeLog @@ -1,3 +1,12 @@ +2008-09-19 Jakub Jelinek <jakub@redhat.com> + Andreas Tobler <a.tobler@schweiz.org> + + * config/bsd/proc.c: New file. + * configure.tgt (*-*-darwin*): Use config_path "bsd posix". + * configure.ac: Check for header <sys/sysctl.h> + * configure: Regenerate. + * config.h.in: Likewise. + 2008-09-05 Janis Johnson <janis187@us.ibm.com> * testsuite/ligbomp.c/c.exp: Unset lang_test_file only if it exists. diff --git a/libgomp/Makefile.in b/libgomp/Makefile.in index a0e008f34e0..81cbb01702e 100644 --- a/libgomp/Makefile.in +++ b/libgomp/Makefile.in @@ -38,7 +38,6 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ -LIBOBJDIR = DIST_COMMON = $(am__configure_deps) $(srcdir)/../config.guess \ $(srcdir)/../config.sub $(srcdir)/../depcomp \ $(srcdir)/../install-sh $(srcdir)/../ltmain.sh \ diff --git a/libgomp/config/bsd/proc.c b/libgomp/config/bsd/proc.c new file mode 100644 index 00000000000..513d8df3910 --- /dev/null +++ b/libgomp/config/bsd/proc.c @@ -0,0 +1,117 @@ +/* Copyright (C) 2005, 2006, 2008 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU OpenMP Library (libgomp). + + Libgomp is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + Libgomp 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 Lesser General Public License for + more details. + + You should have received a copy of the GNU Lesser General Public License + along with libgomp; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. */ + +/* As a special exception, if you link this library with other files, some + of which are compiled with GCC, to produce an executable, this library + 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. */ + +/* This file contains system specific routines related to counting + online processors and dynamic load balancing. It is expected that + a system may well want to write special versions of each of these. + + The following implementation uses a mix of POSIX and BSD routines. */ + +#include "libgomp.h" +#include <unistd.h> +#include <stdlib.h> +#ifdef HAVE_GETLOADAVG +# ifdef HAVE_SYS_LOADAVG_H +# include <sys/loadavg.h> +# endif +#endif +#ifdef HAVE_SYS_SYSCTL_H +# include <sys/sysctl.h> +#endif + +static int +get_num_procs (void) +{ +#ifdef _SC_NPROCESSORS_ONLN + return sysconf (_SC_NPROCESSORS_ONLN); +#elif defined HW_NCPU + int ncpus = 1; + size_t len = sizeof(ncpus); + sysctl((int[2]) {CTL_HW, HW_NCPU}, 2, &ncpus, &len, NULL, 0); + return ncpus; +#else + return 0; +#endif +} + +/* At startup, determine the default number of threads. It would seem + this should be related to the number of cpus online. */ + +void +gomp_init_num_threads (void) +{ + int ncpus = get_num_procs (); + + if (ncpus > 0) + gomp_global_icv.nthreads_var = ncpus; +} + +/* When OMP_DYNAMIC is set, at thread launch determine the number of + threads we should spawn for this team. */ +/* ??? I have no idea what best practice for this is. Surely some + function of the number of processors that are *still* online and + the load average. Here I use the number of processors online + minus the 15 minute load average. */ + +unsigned +gomp_dynamic_max_threads (void) +{ + unsigned n_onln, loadavg; + unsigned nthreads_var = gomp_icv (false)->nthreads_var; + + n_onln = get_num_procs (); + if (!n_onln || n_onln > nthreads_var) + n_onln = nthreads_var; + + loadavg = 0; +#ifdef HAVE_GETLOADAVG + { + double dloadavg[3]; + if (getloadavg (dloadavg, 3) == 3) + { + /* Add 0.1 to get a kind of biased rounding. */ + loadavg = dloadavg[2] + 0.1; + } + } +#endif + + if (loadavg >= n_onln) + return 1; + else + return n_onln - loadavg; +} + +int +omp_get_num_procs (void) +{ + int ncpus = get_num_procs (); + if (ncpus <= 0) + ncpus = gomp_icv (false)->nthreads_var; + return ncpus; +} + +ialias (omp_get_num_procs) diff --git a/libgomp/configure b/libgomp/configure index 1fc0891b26f..a9f7df510f0 100755 --- a/libgomp/configure +++ b/libgomp/configure @@ -13540,7 +13540,8 @@ fi -for ac_header in unistd.h semaphore.h sys/loadavg.h sys/time.h + +for ac_header in unistd.h semaphore.h sys/loadavg.h sys/time.h sys/time.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then diff --git a/libgomp/configure.ac b/libgomp/configure.ac index 21aed2ba819..db8e2811a30 100644 --- a/libgomp/configure.ac +++ b/libgomp/configure.ac @@ -154,7 +154,7 @@ AC_SUBST(libtool_VERSION) AC_STDC_HEADERS AC_HEADER_TIME ACX_HEADER_STRING -AC_CHECK_HEADERS(unistd.h semaphore.h sys/loadavg.h sys/time.h) +AC_CHECK_HEADERS(unistd.h semaphore.h sys/loadavg.h sys/time.h sys/time.h) GCC_HEADER_STDINT(gstdint.h) diff --git a/libgomp/configure.tgt b/libgomp/configure.tgt index ef44a12a4bd..d66899fbf5f 100644 --- a/libgomp/configure.tgt +++ b/libgomp/configure.tgt @@ -111,6 +111,10 @@ case "${target}" in XLDFLAGS="${XLDFLAGS} -lposix4" ;; + *-*-darwin*) + config_path="bsd posix" + ;; + *) ;; diff --git a/libgomp/testsuite/Makefile.in b/libgomp/testsuite/Makefile.in index 6ce379e8a0c..ae1806fb2da 100644 --- a/libgomp/testsuite/Makefile.in +++ b/libgomp/testsuite/Makefile.in @@ -36,7 +36,6 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ -LIBOBJDIR = subdir = testsuite DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 99340ec117c..cbb6671a568 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,8 @@ +2008-09-21 Paolo Carlini <paolo.carlini@oracle.com> + + * include/bits/stl_algo.h (minmax(initializer_list<>): Use make_pair, + consistently with the other overload for initializer_list. + 2008-09-19 Johannes Singler <singler@ira.uka.de> PR libstdc++/37470 diff --git a/libstdc++-v3/include/bits/stl_algo.h b/libstdc++-v3/include/bits/stl_algo.h index 373881c7f1b..d956376d8dd 100644 --- a/libstdc++-v3/include/bits/stl_algo.h +++ b/libstdc++-v3/include/bits/stl_algo.h @@ -4121,7 +4121,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) { pair<const _Tp*, const _Tp*> __p = std::minmax_element(__l.begin(), __l.end()); - return std::pair<_Tp, _Tp>(*__p.first, *__p.second); + return std::make_pair(*__p.first, *__p.second); } template<typename _Tp, typename _Compare> |