summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog373
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/ada/ChangeLog4
-rw-r--r--gcc/ada/gnatvsn.ads4
-rw-r--r--gcc/alloc-pool.c6
-rw-r--r--gcc/c-family/ChangeLog17
-rw-r--r--gcc/c-family/c-common.c36
-rw-r--r--gcc/c-family/c.opt2
-rw-r--r--gcc/c/ChangeLog35
-rw-r--r--gcc/c/c-decl.c40
-rw-r--r--gcc/c/c-parser.c72
-rw-r--r--gcc/c/c-tree.h3
-rw-r--r--gcc/c/c-typeck.c65
-rw-r--r--gcc/cgraph.c4
-rw-r--r--gcc/cgraphunit.c6
-rw-r--r--gcc/config.in12
-rw-r--r--gcc/config/arm/aarch-common.c8
-rw-r--r--gcc/config/arm/arm.c8
-rw-r--r--gcc/config/arm/arm.md12
-rw-r--r--gcc/config/arm/predicates.md3
-rw-r--r--gcc/config/avr/avr.c6
-rw-r--r--gcc/config/i386/i386-c.c7
-rw-r--r--gcc/config/i386/i386.md13
-rw-r--r--gcc/config/m68k/m68k.md4
-rw-r--r--gcc/config/rs6000/altivec.md112
-rw-r--r--gcc/config/rs6000/dfp.md69
-rw-r--r--gcc/config/rs6000/predicates.md5
-rw-r--r--gcc/config/rs6000/rs6000-builtin.def135
-rw-r--r--gcc/config/rs6000/rs6000.c82
-rw-r--r--gcc/config/rs6000/rs6000.h10
-rw-r--r--gcc/config/rs6000/rs6000.md208
-rw-r--r--gcc/config/sol2.h1
-rw-r--r--gcc/config/sparc/sparc.md13
-rw-r--r--gcc/config/sparc/sparc.opt4
-rw-r--r--gcc/config/sparc/sync.md19
-rwxr-xr-xgcc/configure170
-rw-r--r--gcc/configure.ac95
-rw-r--r--gcc/cp/ChangeLog12
-rw-r--r--gcc/cp/parser.c45
-rw-r--r--gcc/cselib.c66
-rw-r--r--gcc/doc/extend.texi67
-rw-r--r--gcc/doc/install.texi3
-rw-r--r--gcc/doc/invoke.texi9
-rw-r--r--gcc/dwarf2out.c56
-rw-r--r--gcc/expr.c12
-rw-r--r--gcc/expr.h8
-rw-r--r--gcc/fortran/ChangeLog20
-rw-r--r--gcc/fortran/arith.c11
-rw-r--r--gcc/fortran/gfortran.h4
-rw-r--r--gcc/fortran/simplify.c32
-rw-r--r--gcc/gimple-ssa-strength-reduction.c17
-rw-r--r--gcc/gimplify.c63
-rw-r--r--gcc/go/ChangeLog13
-rw-r--r--gcc/go/go-gcc.cc168
-rw-r--r--gcc/go/gofrontend/backend.h20
-rw-r--r--gcc/go/gofrontend/expressions.cc141
-rw-r--r--gcc/go/gofrontend/expressions.h148
-rw-r--r--gcc/go/gofrontend/gogo-tree.cc882
-rw-r--r--gcc/go/gofrontend/gogo.cc793
-rw-r--r--gcc/go/gofrontend/gogo.h36
-rw-r--r--gcc/go/gofrontend/statements.cc22
-rw-r--r--gcc/graphite-scop-detection.c6
-rw-r--r--gcc/haifa-sched.c4
-rw-r--r--gcc/omp-low.c14
-rw-r--r--gcc/passes.c133
-rw-r--r--gcc/rtl.h2
-rw-r--r--gcc/rtlanal.c10
-rw-r--r--gcc/system.h2
-rw-r--r--gcc/testsuite/ChangeLog160
-rw-r--r--gcc/testsuite/c-c++-common/gomp/atomic-16.c40
-rw-r--r--gcc/testsuite/c-c++-common/gomp/pr60823-2.c1
-rw-r--r--gcc/testsuite/c-c++-common/pr60156.c9
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alias-decl-43.C4
-rw-r--r--gcc/testsuite/g++.dg/debug/dwarf2/dwarf4-nested.C55
-rw-r--r--gcc/testsuite/g++.dg/debug/dwarf2/dwarf4-typedef.C2
-rw-r--r--gcc/testsuite/g++.dg/ipa/devirt-27.C2
-rw-r--r--gcc/testsuite/g++.dg/opt/pr60912.C18
-rw-r--r--gcc/testsuite/g++.dg/vect/pr60896.cc44
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/20140425-1.c23
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr60822.c24
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr60822.x7
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr60960.c38
-rw-r--r--gcc/testsuite/gcc.dg/Wstrict-overflow-14.c2
-rw-r--r--gcc/testsuite/gcc.dg/Wstrict-overflow-15.c2
-rw-r--r--gcc/testsuite/gcc.dg/Wstrict-overflow-18.c2
-rw-r--r--gcc/testsuite/gcc.dg/graphite/pr60979.c37
-rw-r--r--gcc/testsuite/gcc.dg/lto/pr60911_0.c21
-rw-r--r--gcc/testsuite/gcc.dg/pr18079-2.c16
-rw-r--r--gcc/testsuite/gcc.dg/pr18079.c33
-rw-r--r--gcc/testsuite/gcc.dg/pr60114.c31
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr60930.c22
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/alias-30.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/isolate-1.c1
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/isolate-2.c1
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/isolate-3.c1
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/isolate-4.c1
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/isolate-5.c1
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp91.c22
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr60505.c2
-rw-r--r--gcc/testsuite/gcc.target/arm/tail-long-call.c12
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bcd-1.c27
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bcd-2.c44
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bcd-3.c103
-rw-r--r--gcc/testsuite/gcc.target/powerpc/dfp-builtin-1.c88
-rw-r--r--gcc/testsuite/gcc.target/powerpc/dfp-builtin-2.c88
-rw-r--r--gcc/testsuite/gcc.target/powerpc/extend-divide-1.c34
-rw-r--r--gcc/testsuite/gcc.target/powerpc/extend-divide-2.c34
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pack01.c91
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pack02.c95
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pack03.c88
-rw-r--r--gcc/testsuite/gfortran.dg/namelist_utf8.f9030
-rw-r--r--gcc/testsuite/gfortran.dg/no_range_check_3.f9012
-rw-r--r--gcc/tree-nested.c22
-rw-r--r--gcc/tree-pass.h4
-rw-r--r--gcc/tree-ssa-structalias.c41
-rw-r--r--gcc/tree-ssa-threadedge.c2
-rw-r--r--gcc/tree-vect-generic.c3
-rw-r--r--gcc/tree-vect-patterns.c5
-rw-r--r--gcc/tree-vrp.c98
-rw-r--r--gcc/tree.h3
120 files changed, 4326 insertions, 1706 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a29383083b3..67a4645a87a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,376 @@
+2014-04-28 Richard Biener <rguenther@suse.de>
+
+ * tree-vrp.c (vrp_var_may_overflow): Remove.
+ (vrp_visit_phi_node): Rather than bumping to +-INF possibly
+ with overflow immediately bump to one before that value and
+ let iteration figure out overflow status.
+
+2014-04-28 Richard Biener <rguenther@suse.de>
+
+ * configure.ac: Do valgrind header checks unconditionally.
+ Add --enable-valgrind-annotations.
+ * system.h: Guard valgrind header inclusion with
+ ENABLE_VALGRIND_ANNOTATIONS instead of ENABLE_VALGRIND_CHECKING.
+ * alloc-pool.c (pool_alloc, pool_free): Use
+ ENABLE_VALGRIND_ANNOTATIONS instead of ENABLE_VALGRIND_CHECKING
+ to guard possibly dead code.
+ * config.in: Regenerated.
+ * configure: Likewise.
+
+2014-04-28 Jeff Law <law@redhat.com>
+
+ PR tree-optimization/60902
+ * tree-ssa-threadedge.c
+ (record_temporary_equivalences_from_stmts_at_dest): Only iterate
+ over real defs when invalidating outputs from statements that do not
+ produce useful outputs for threading.
+
+2014-04-28 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/60979
+ * graphite-scop-detection.c (scopdet_basic_block_info): Reject
+ SCOPs that end in a block with a successor with abnormal
+ predecessors.
+
+2014-04-28 Richard Biener <rguenther@suse.de>
+
+ * tree-pass.h (execute_pass_list): Adjust prototype.
+ * passes.c (pass_manager::execute_early_local_passes):
+ Adjust.
+ (do_per_function): Change callback signature, push all actual
+ work to the callbals.
+ (do_per_function_toporder): Likewise.
+ (execute_function_dump): Adjust.
+ (execute_function_todo): Likewise.
+ (clear_last_verified): Likewise.
+ (verify_curr_properties): Likewise.
+ (update_properties_after_pass): Likewise.
+ (execute_pass_list_1): Split out from ...
+ (execute_pass_list): ... here. Adjust.
+ (execute_ipa_pass_list): Likewise.
+ * cgraphunit.c (cgraph_add_new_function): Adjust.
+ (analyze_function): Likewise.
+ (expand_function): Likewise.
+ * cgraph.c (release_function_body): Free dominance info
+ here instead of asserting it was magically freed elsewhere.
+
+2014-04-28 Eric Botcazou <ebotcazou@adacore.com>
+
+ * configure.ac: Tweak GAS check for LEON instructions on SPARC.
+ * configure: Regenerate.
+ * config/sparc/sparc.opt (muser-mode): New option.
+ * config/sparc/sync.md (atomic_compare_and_swap<mode>_1): Do not enable
+ for LEON3.
+ (atomic_compare_and_swap_leon3_1): New instruction for LEON3.
+ * doc/invoke.texi (SPARC options): Document -muser-mode.
+
+2014-04-27 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * cselib.c (find_slot_memmode): Delete.
+ (cselib_hasher): Change compare_type to a struct.
+ (cselib_hasher::equal): Update accordingly. Don't expect wrapped
+ constants.
+ (preserve_constants_and_equivs): Adjust for new compare_type.
+ (cselib_find_slot): Likewise. Take the mode of the rtx as argument.
+ (wrap_constant): Delete.
+ (cselib_lookup_mem, cselib_lookup_1): Update calls to cselib_find_slot.
+
+2014-04-26 Markus Trippelsdorf <markus@trippelsdorf.de>
+
+ * doc/install.texi (Building with profile feedback): Remove
+ outdated sentence.
+
+2014-04-26 Tom de Vries <tom@codesourcery.com>
+
+ * config/i386/i386.md (define_expand "ldexpxf3"): Fix out-of-bounds
+ array accesses.
+
+2014-04-25 Cary Coutant <ccoutant@google.com>
+
+ PR debug/60929
+ * dwarf2out.c (should_move_die_to_comdat): A type definition
+ can contain a subprogram definition, but don't move it to a
+ comdat unit.
+ (clone_as_declaration): Copy DW_AT_abstract_origin attribute.
+ (generate_skeleton_bottom_up): Remove DW_AT_object_pointer attribute
+ from original DIE.
+ (clone_tree_hash): Rename to...
+ (clone_tree_partial): ...this; change callers. Copy
+ DW_TAG_subprogram DIEs as declarations.
+ (copy_decls_walk): Don't copy children of a declaration into a
+ type unit.
+
+2014-04-25 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/60969
+ * config/i386/i386.md (*movsf_internal): Set MODE to SI for
+ alternative 12.
+
+2014-04-25 Jiong Wang <jiong.wang@arm.com>
+
+ * config/arm/predicates.md (call_insn_operand): Add long_call check.
+ * config/arm/arm.md (sibcall, sibcall_value): Force the address to
+ reg for long_call.
+ * config/arm/arm.c (arm_function_ok_for_sibcall): Remove long_call
+ restriction.
+
+2014-04-25 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/arm/arm.c (arm_cortex_a8_tune): Initialise
+ T16-related fields.
+
+2014-04-25 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ PR tree-optimization/60930
+ * gimple-ssa-strength-reduction.c (create_mul_imm_cand): Reject
+ creating a multiply candidate by folding two constant
+ multiplicands when the result overflows.
+
+2014-04-25 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/60960
+ * tree-vect-generic.c (expand_vector_operation): Only call
+ expand_vector_divmod if type's mode satisfies VECTOR_MODE_P.
+
+2014-04-25 Tom de Vries <tom@codesourcery.com>
+
+ * expr.c (clobber_reg_mode): New function.
+ * expr.h (clobber_reg): New function.
+
+2014-04-25 Tom de Vries <tom@codesourcery.com>
+
+ * rtlanal.c (find_all_hard_reg_sets): Note INSN_CALL_FUNCTION_USAGE
+ clobbers.
+
+2014-04-25 Radovan Obradovic <robradovic@mips.com>
+ Tom de Vries <tom@codesourcery.com>
+
+ * rtlanal.c (find_all_hard_reg_sets): Add bool implicit parameter and
+ handle.
+ * rtl.h (find_all_hard_reg_sets): Add bool parameter.
+ * haifa-sched.c (recompute_todo_spec, check_clobbered_conditions): Add
+ new argument to find_all_hard_reg_sets call.
+
+2014-04-25 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/arm/aarch-common.c (aarch_rev16_shright_mask_imm_p):
+ Use HOST_WIDE_INT_C for mask literal.
+ (aarch_rev16_shleft_mask_imm_p): Likewise.
+
+2014-04-25 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR target/60941
+ * config/sparc/sparc.md (ashlsi3_extend): Delete.
+
+2014-04-25 Marc Glisse <marc.glisse@inria.fr>
+
+ PR preprocessor/56540
+ * config/i386/i386-c.c (ix86_target_macros): Define
+ __SIZEOF_FLOAT80__ and __SIZEOF_FLOAT128__.
+
+2014-04-25 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * configure.ac (tga_func): Remove.
+ (LIB_TLS_SPEC): Remove.
+ * configure: Regenerate.
+ * config.in: Regenerate.
+ * config/sol2.h (LIB_SPEC): Don't use LIB_TLS_SPEC.
+
+2014-04-25 Richard Biener <rguenther@suse.de>
+
+ PR ipa/60912
+ * tree-ssa-structalias.c (ipa_pta_execute): Compute direct
+ call stmt use/clobber sets during stmt walk instead of
+ walking the possibly incomplete set of caller edges.
+
+2014-04-25 Richard Biener <rguenther@suse.de>
+
+ PR ipa/60911
+ * passes.c (apply_ipa_transforms): Inline into only caller ...
+ (execute_one_pass): ... here. Properly bring in function
+ bodies for nodes we want to apply IPA transforms to.
+
+2014-04-24 Cong Hou <congh@google.com>
+
+ PR tree-optimization/60896
+ * tree-vect-patterns.c (vect_recog_dot_prod_pattern): Pick up
+ all statements in PATTERN_DEF_SEQ in recognized widen-mult pattern.
+ (vect_mark_pattern_stmts): Set the def type of all statements in
+ PATTERN_DEF_SEQ as vect_internal_def.
+
+2014-04-24 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * doc/extend.texi (PowerPC Built-in Functions): Document new
+ powerpc extended divide, bcd, pack/unpack 128-bit, builtin
+ functions.
+ (PowerPC AltiVec/VSX Built-in Functions): Likewise.
+
+ * config/rs6000/predicates.md (const_0_to_3_operand): New
+ predicate to match 0..3 integer constants.
+
+ * config/rs6000/rs6000-builtin.def (BU_DFP_MISC_1): Add new macros
+ to support adding miscellaneous builtin functions.
+ (BU_DFP_MISC_2): Likewise.
+ (BU_P7_MISC_1): Likewise.
+ (BU_P7_MISC_2): Likewise.
+ (BU_P8V_MISC_3): Likewise.
+ (BU_MISC_1): Likewise.
+ (BU_MISC_2): Likewise.
+ (DIVWE): Add extended divide builtin functions.
+ (DIVWEO): Likewise.
+ (DIVWEU): Likewise.
+ (DIVWEUO): Likewise.
+ (DIVDE): Likewise.
+ (DIVDEO): Likewise.
+ (DIVDEU): Likewise.
+ (DIVDEUO): Likewise.
+ (DXEX): Add decimal floating-point builtin functions.
+ (DXEXQ): Likewise.
+ (DDEDPD): Likewise.
+ (DDEDPDQ): Likewise.
+ (DENBCD): Likewise.
+ (DENBCDQ): Likewise.
+ (DIEX): Likewise.
+ (DIEXQ): Likewise.
+ (DSCLI): Likewise.
+ (DSCLIQ): Likewise.
+ (DSCRI): Likewise.
+ (DSCRIQ): Likewise.
+ (CDTBCD): Add new BCD builtin functions.
+ (CBCDTD): Likewise.
+ (ADDG6S): Likewise.
+ (BCDADD): Likewise.
+ (BCDADD_LT): Likewise.
+ (BCDADD_EQ): Likewise.
+ (BCDADD_GT): Likewise.
+ (BCDADD_OV): Likewise.
+ (BCDSUB): Likewise.
+ (BCDSUB_LT): Likewise.
+ (BCDSUB_EQ): Likewise.
+ (BCDSUB_GT): Likewise.
+ (BCDSUB_OV): Likewise.
+ (PACK_TD): Add new pack/unpack 128-bit type builtin functions.
+ (UNPACK_TD): Likewise.
+ (PACK_TF): Likewise.
+ (UNPACK_TF): Likewise.
+ (UNPACK_TF_0): Likewise.
+ (UNPACK_TF_1): Likewise.
+ (PACK_V1TI): Likewise.
+ (UNPACK_V1TI): Likewise.
+
+ * config/rs6000/rs6000.c (rs6000_builtin_mask_calculate): Add
+ support for decimal floating point builtin functions.
+ (rs6000_expand_ternop_builtin): Add checks for the new builtin
+ functions that take constant arguments.
+ (rs6000_invalid_builtin): Add decimal floating point builtin
+ support.
+ (rs6000_init_builtins): Setup long double, _Decimal64, and
+ _Decimal128 types for new builtin functions.
+ (builtin_function_type): Set the unsigned flags appropriately for
+ the new builtin functions.
+ (rs6000_opt_masks): Add support for decimal floating point builtin
+ functions.
+
+ * config/rs6000/rs6000.h (RS6000_BTM_DFP): Add support for decimal
+ floating point builtin functions.
+ (RS6000_BTM_COMMON): Likewise.
+ (RS6000_BTI_long_double): Likewise.
+ (RS6000_BTI_dfloat64): Likewise.
+ (RS6000_BTI_dfloat128): Likewise.
+ (long_double_type_internal_node): Likewise.
+ (dfloat64_type_internal_node): Likewise.
+ (dfloat128_type_internal_node): Likewise.
+
+ * config/rs6000/altivec.h (UNSPEC_BCDADD): Add support for ISA
+ 2.07 bcd arithmetic instructions.
+ (UNSPEC_BCDSUB): Likewise.
+ (UNSPEC_BCD_OVERFLOW): Likewise.
+ (UNSPEC_BCD_ADD_SUB): Likewise.
+ (bcd_add_sub): Likewise.
+ (BCD_TEST): Likewise.
+ (bcd<bcd_add_sub>): Likewise.
+ (bcd<bcd_add_sub>_test): Likewise.
+ (bcd<bcd_add_sub>_test2): Likewise.
+ (bcd<bcd_add_sub>_<code>): Likewise.
+ (peephole2 for combined bcd ops): Likewise.
+
+ * config/rs6000/dfp.md (UNSPEC_DDEDPD): Add support for new
+ decimal floating point builtin functions.
+ (UNSPEC_DENBCD): Likewise.
+ (UNSPEC_DXEX): Likewise.
+ (UNSPEC_DIEX): Likewise.
+ (UNSPEC_DSCLI): Likewise.
+ (UNSPEC_DSCRI): Likewise.
+ (D64_D128): Likewise.
+ (dfp_suffix): Likewise.
+ (dfp_ddedpd_<mode>): Likewise.
+ (dfp_denbcd_<mode>): Likewise.
+ (dfp_dxex_<mode>): Likewise.
+ (dfp_diex_<mode>): Likewise.
+ (dfp_dscli_<mode>): Likewise.
+ (dfp_dscri_<mode>): Likewise.
+
+ * config/rs6000/rs6000.md (UNSPEC_ADDG6S): Add support for new BCD
+ builtin functions.
+ (UNSPEC_CDTBCD): Likewise.
+ (UNSPEC_CBCDTD): Likewise.
+ (UNSPEC_DIVE): Add support for new extended divide builtin
+ functions.
+ (UNSPEC_DIVEO): Likewise.
+ (UNSPEC_DIVEU): Likewise.
+ (UNSPEC_DIVEUO): Likewise.
+ (UNSPEC_UNPACK_128BIT): Add support for new builtin functions to
+ pack/unpack 128-bit types.
+ (UNSPEC_PACK_128BIT): Likewise.
+ (idiv_ldiv): New mode attribute to set the 32/64-bit divide type.
+ (udiv<mode>3): Use idiv_ldiv mode attribute.
+ (div<mode>3): Likewise.
+ (addg6s): Add new BCD builtin functions.
+ (cdtbcd): Likewise.
+ (cbcdtd): Likewise.
+ (UNSPEC_DIV_EXTEND): Add support for new extended divide
+ instructions.
+ (div_extend): Likewise.
+ (div<div_extend>_<mode>"): Likewise.
+ (FP128_64): Add support for new builtin functions to pack/unpack
+ 128-bit types.
+ (unpack<mode>): Likewise.
+ (unpacktf_0): Likewise.
+ (unpacktf_1): Likewise.
+ (unpack<mode>_dm): Likewise.
+ (unpack<mode>_nodm): Likewise.
+ (pack<mode>): Likewise.
+ (unpackv1ti): Likewise.
+ (packv1ti): Likewise.
+
+2014-04-24 Vishnu K S <Vishnu.k_s@atmel.com>
+
+ * gcc/config/avr/avr.c: Add comment on why -fdelete-null-pointer-checks
+ is disabled.
+
+2014-04-24 Jakub Jelinek <jakub@redhat.com>
+
+ * tree.h (OMP_CLAUSE_LINEAR_GIMPLE_SEQ): Define.
+ * gimplify.c (omp_is_private): Change last argument's type to int.
+ Only diagnose lastprivate if the simd argument is 1, only diagnose
+ linear if the simd argument is 2.
+ (gimplify_omp_for): Adjust omp_is_private callers. When adding
+ lastprivate or private, add the clause to OMP_FOR_CLAUSES. Pass
+ GOVD_EXPLICIT to omp_add_variable. For simd with collapse == 1
+ create OMP_CLAUSE_LINEAR rather than OMP_CLAUSE_PRIVATE for var.
+ If var != decl and decl is in OMP_CLAUSE_LINEAR, gimplify decl
+ increment to OMP_CLAUSE_LINEAR_GIMPLE_SEQ.
+ * omp-low.c (scan_sharing_clauses, lower_lastprivate_clauses): Handle
+ OMP_CLAUSE_LINEAR_GIMPLE_SEQ.
+ * tree-nested.c (convert_nonlocal_omp_clauses,
+ convert_local_omp_clauses): Handle OMP_CLAUSE_LINEAR.
+
+2014-04-24 Segher Boessenkool <segher@kernel.crashing.org>
+
+ PR target/60822
+ * config/m68k/m68k.md (extendplussidi): Don't allow memory for
+ operand 1.
+
2014-04-24 Dimitris Papavasiliou <dpapavas@gmail.com>
* flag-types.h (enum ivar_visibility): Add.
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index dd60d348052..2eee80b2cf1 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20140424
+20140428
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 6dc0c11ed3f..a31cd3c2f11 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,7 @@
+2014-04-26 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnatvsn.ads (Library_Version): Bump to 4.10.
+
2014-04-23 Eric Botcazou <ebotcazou@adacore.com>
Revert
diff --git a/gcc/ada/gnatvsn.ads b/gcc/ada/gnatvsn.ads
index d1f95621b98..a0155fe7cb9 100644
--- a/gcc/ada/gnatvsn.ads
+++ b/gcc/ada/gnatvsn.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -82,7 +82,7 @@ package Gnatvsn is
-- Prefix generated by binder. If it is changed, be sure to change
-- GNAT.Compiler_Version.Ver_Prefix as well.
- Library_Version : constant String := "4.9";
+ Library_Version : constant String := "4.10";
-- Library version. This value must be updated when the compiler
-- version number Gnat_Static_Version_String is updated.
--
diff --git a/gcc/alloc-pool.c b/gcc/alloc-pool.c
index dfb13ce55fb..87fbd8556fb 100644
--- a/gcc/alloc-pool.c
+++ b/gcc/alloc-pool.c
@@ -250,7 +250,7 @@ void *
pool_alloc (alloc_pool pool)
{
alloc_pool_list header;
-#ifdef ENABLE_VALGRIND_CHECKING
+#ifdef ENABLE_VALGRIND_ANNOTATIONS
int size;
#endif
@@ -265,7 +265,7 @@ pool_alloc (alloc_pool pool)
}
gcc_checking_assert (pool);
-#ifdef ENABLE_VALGRIND_CHECKING
+#ifdef ENABLE_VALGRIND_ANNOTATIONS
size = pool->elt_size - offsetof (allocation_object, u.data);
#endif
@@ -334,7 +334,7 @@ void
pool_free (alloc_pool pool, void *ptr)
{
alloc_pool_list header;
-#if defined(ENABLE_VALGRIND_CHECKING) || defined(ENABLE_CHECKING)
+#if defined(ENABLE_VALGRIND_ANNOTATIONS) || defined(ENABLE_CHECKING)
int size;
size = pool->elt_size - offsetof (allocation_object, u.data);
#endif
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 1b466ac4b51..fb0d102eac3 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,20 @@
+2014-04-25 Marek Polacek <polacek@redhat.com>
+
+ PR c/18079
+ * c-common.c (handle_noinline_attribute): Warn if the attribute
+ conflicts with always_inline attribute.
+ (handle_always_inline_attribute): Warn if the attribute conflicts
+ with noinline attribute.
+
+2014-04-25 Marek Polacek <polacek@redhat.com>
+
+ PR c/60156
+ * c-common.c (check_main_parameter_types): Warn about variadic main.
+
+2014-04-24 Mike Stump <mikestump@comcast.net>
+
+ * c.opt (Wshadow-ivar): Default to on.
+
2014-04-24 Dimitris Papavasiliou <dpapavas@gmail.com>
* c.opt (Wshadow-ivar, flocal-ivars, fivar-visibility): Add.
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 347be6e8208..0afe2f5ab38 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -2229,6 +2229,10 @@ check_main_parameter_types (tree decl)
if (argct > 0 && (argct < 2 || argct > 3))
pedwarn (input_location, OPT_Wmain,
"%q+D takes only zero or two arguments", decl);
+
+ if (stdarg_p (TREE_TYPE (decl)))
+ pedwarn (input_location, OPT_Wmain,
+ "%q+D declared as variadic function", decl);
}
/* vector_targets_convertible_p is used for vector pointer types. The
@@ -6549,8 +6553,8 @@ handle_hot_attribute (tree *node, tree name, tree ARG_UNUSED (args),
{
if (lookup_attribute ("cold", DECL_ATTRIBUTES (*node)) != NULL)
{
- warning (OPT_Wattributes, "%qE attribute conflicts with attribute %s",
- name, "cold");
+ warning (OPT_Wattributes, "%qE attribute ignored due to conflict "
+ "with attribute %qs", name, "cold");
*no_add_attrs = true;
}
/* Most of the rest of the hot processing is done later with
@@ -6577,8 +6581,8 @@ handle_cold_attribute (tree *node, tree name, tree ARG_UNUSED (args),
{
if (lookup_attribute ("hot", DECL_ATTRIBUTES (*node)) != NULL)
{
- warning (OPT_Wattributes, "%qE attribute conflicts with attribute %s",
- name, "hot");
+ warning (OPT_Wattributes, "%qE attribute ignored due to conflict "
+ "with attribute %qs", name, "hot");
*no_add_attrs = true;
}
/* Most of the rest of the cold processing is done later with
@@ -6651,7 +6655,16 @@ handle_noinline_attribute (tree *node, tree name,
int ARG_UNUSED (flags), bool *no_add_attrs)
{
if (TREE_CODE (*node) == FUNCTION_DECL)
- DECL_UNINLINABLE (*node) = 1;
+ {
+ if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (*node)))
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored due to conflict "
+ "with attribute %qs", name, "always_inline");
+ *no_add_attrs = true;
+ }
+ else
+ DECL_UNINLINABLE (*node) = 1;
+ }
else
{
warning (OPT_Wattributes, "%qE attribute ignored", name);
@@ -6689,9 +6702,16 @@ handle_always_inline_attribute (tree *node, tree name,
{
if (TREE_CODE (*node) == FUNCTION_DECL)
{
- /* Set the attribute and mark it for disregarding inline
- limits. */
- DECL_DISREGARD_INLINE_LIMITS (*node) = 1;
+ if (lookup_attribute ("noinline", DECL_ATTRIBUTES (*node)))
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored due to conflict "
+ "with %qs attribute", name, "noinline");
+ *no_add_attrs = true;
+ }
+ else
+ /* Set the attribute and mark it for disregarding inline
+ limits. */
+ DECL_DISREGARD_INLINE_LIMITS (*node) = 1;
}
else
{
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 2bc06ba7bba..94447082fb5 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -685,7 +685,7 @@ ObjC ObjC++ Var(warn_selector) Warning
Warn if a selector has multiple methods
Wshadow-ivar
-ObjC ObjC++ Var(warn_shadow_ivar) Init(-1) Warning
+ObjC ObjC++ Var(warn_shadow_ivar) Init(1) Warning
Warn if a local declaration hides an instance variable
Wsequence-point
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 2d182f354d5..80841af40ee 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,38 @@
+2014-04-25 Marek Polacek <polacek@redhat.com>
+
+ PR c/18079
+ * c-decl.c (diagnose_mismatched_decls): Warn for mismatched
+ always_inline/noinline and hot/cold attributes.
+
+2014-04-25 Marek Polacek <polacek@redhat.com>
+
+ PR c/60114
+ * c-parser.c (c_parser_initelt): Pass input_location to
+ process_init_element.
+ (c_parser_initval): Pass loc to process_init_element.
+ * c-tree.h (process_init_element): Adjust declaration.
+ * c-typeck.c (push_init_level): Pass input_location to
+ process_init_element.
+ (pop_init_level): Likewise.
+ (set_designator): Likewise.
+ (output_init_element): Add location_t parameter. Pass loc to
+ digest_init.
+ (output_pending_init_elements): Pass input_location to
+ output_init_element.
+ (process_init_element): Add location_t parameter. Pass loc to
+ output_init_element.
+
+2014-04-24 Prathamesh Kulkarni <bilbotheelffriend@gmail.com>
+
+ * c-parser.c (c_parser_sizeof_expression): Reorganize slightly to
+ avoid goto.
+
+2014-04-24 Jakub Jelinek <jakub@redhat.com>
+
+ * c-parser.c (c_parser_omp_atomic): Allow seq_cst before
+ atomic-clause, allow comma in between atomic-clause and
+ seq_cst.
+
2014-04-22 Jakub Jelinek <jakub@redhat.com>
PR c/59073
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 82b882e3cd1..90808eda618 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -2099,18 +2099,38 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
/* Diagnose inline __attribute__ ((noinline)) which is silly. */
if (DECL_DECLARED_INLINE_P (newdecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
- {
- warned |= warning (OPT_Wattributes,
- "inline declaration of %qD follows "
- "declaration with attribute noinline", newdecl);
- }
+ warned |= warning (OPT_Wattributes,
+ "inline declaration of %qD follows "
+ "declaration with attribute noinline", newdecl);
else if (DECL_DECLARED_INLINE_P (olddecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
- {
- warned |= warning (OPT_Wattributes,
- "declaration of %q+D with attribute "
- "noinline follows inline declaration ", newdecl);
- }
+ warned |= warning (OPT_Wattributes,
+ "declaration of %q+D with attribute "
+ "noinline follows inline declaration ", newdecl);
+ else if (lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl))
+ && lookup_attribute ("always_inline", DECL_ATTRIBUTES (olddecl)))
+ warned |= warning (OPT_Wattributes,
+ "declaration of %q+D with attribute "
+ "%qs follows declaration with attribute %qs",
+ newdecl, "noinline", "always_inline");
+ else if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (newdecl))
+ && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
+ warned |= warning (OPT_Wattributes,
+ "declaration of %q+D with attribute "
+ "%qs follows declaration with attribute %qs",
+ newdecl, "always_inline", "noinline");
+ else if (lookup_attribute ("cold", DECL_ATTRIBUTES (newdecl))
+ && lookup_attribute ("hot", DECL_ATTRIBUTES (olddecl)))
+ warned |= warning (OPT_Wattributes,
+ "declaration of %q+D with attribute %qs follows "
+ "declaration with attribute %qs", newdecl, "cold",
+ "hot");
+ else if (lookup_attribute ("hot", DECL_ATTRIBUTES (newdecl))
+ && lookup_attribute ("cold", DECL_ATTRIBUTES (olddecl)))
+ warned |= warning (OPT_Wattributes,
+ "declaration of %q+D with attribute %qs follows "
+ "declaration with attribute %qs", newdecl, "hot",
+ "cold");
}
else /* PARM_DECL, VAR_DECL */
{
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index b1770860ae7..41ae77b541e 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -4219,7 +4219,8 @@ c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
init.original_type = NULL;
c_parser_error (parser, "expected identifier");
c_parser_skip_until_found (parser, CPP_COMMA, NULL);
- process_init_element (init, false, braced_init_obstack);
+ process_init_element (input_location, init, false,
+ braced_init_obstack);
return;
}
}
@@ -4351,7 +4352,8 @@ c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
init.original_type = NULL;
c_parser_error (parser, "expected %<=%>");
c_parser_skip_until_found (parser, CPP_COMMA, NULL);
- process_init_element (init, false, braced_init_obstack);
+ process_init_element (input_location, init, false,
+ braced_init_obstack);
return;
}
}
@@ -4372,18 +4374,19 @@ c_parser_initval (c_parser *parser, struct c_expr *after,
{
struct c_expr init;
gcc_assert (!after || c_dialect_objc ());
+ location_t loc = c_parser_peek_token (parser)->location;
+
if (c_parser_next_token_is (parser, CPP_OPEN_BRACE) && !after)
init = c_parser_braced_init (parser, NULL_TREE, true);
else
{
- location_t loc = c_parser_peek_token (parser)->location;
init = c_parser_expr_no_commas (parser, after);
if (init.value != NULL_TREE
&& TREE_CODE (init.value) != STRING_CST
&& TREE_CODE (init.value) != COMPOUND_LITERAL_EXPR)
init = convert_lvalue_to_rvalue (loc, init, true, true);
}
- process_init_element (init, false, braced_init_obstack);
+ process_init_element (loc, init, false, braced_init_obstack);
}
/* Parse a compound statement (possibly a function body) (C90 6.6.2,
@@ -6514,30 +6517,29 @@ c_parser_sizeof_expression (c_parser *parser)
return ret;
}
if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
+ expr = c_parser_postfix_expression_after_paren_type (parser,
+ type_name,
+ expr_loc);
+ else
{
- expr = c_parser_postfix_expression_after_paren_type (parser,
- type_name,
- expr_loc);
- goto sizeof_expr;
+ /* sizeof ( type-name ). */
+ c_inhibit_evaluation_warnings--;
+ in_sizeof--;
+ return c_expr_sizeof_type (expr_loc, type_name);
}
- /* sizeof ( type-name ). */
- c_inhibit_evaluation_warnings--;
- in_sizeof--;
- return c_expr_sizeof_type (expr_loc, type_name);
}
else
{
expr_loc = c_parser_peek_token (parser)->location;
expr = c_parser_unary_expression (parser);
- sizeof_expr:
- c_inhibit_evaluation_warnings--;
- in_sizeof--;
- mark_exp_read (expr.value);
- if (TREE_CODE (expr.value) == COMPONENT_REF
- && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
- error_at (expr_loc, "%<sizeof%> applied to a bit-field");
- return c_expr_sizeof_expr (expr_loc, expr);
}
+ c_inhibit_evaluation_warnings--;
+ in_sizeof--;
+ mark_exp_read (expr.value);
+ if (TREE_CODE (expr.value) == COMPONENT_REF
+ && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
+ error_at (expr_loc, "%<sizeof%> applied to a bit-field");
+ return c_expr_sizeof_expr (expr_loc, expr);
}
/* Parse an alignof expression. */
@@ -11198,6 +11200,18 @@ c_parser_omp_atomic (location_t loc, c_parser *parser)
if (c_parser_next_token_is (parser, CPP_NAME))
{
const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ if (!strcmp (p, "seq_cst"))
+ {
+ seq_cst = true;
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_COMMA)
+ && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
+ c_parser_consume_token (parser);
+ }
+ }
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
if (!strcmp (p, "read"))
code = OMP_ATOMIC_READ;
@@ -11212,13 +11226,21 @@ c_parser_omp_atomic (location_t loc, c_parser *parser)
if (p)
c_parser_consume_token (parser);
}
- if (c_parser_next_token_is (parser, CPP_NAME))
+ if (!seq_cst)
{
- const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- if (!strcmp (p, "seq_cst"))
+ if (c_parser_next_token_is (parser, CPP_COMMA)
+ && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
+ c_parser_consume_token (parser);
+
+ if (c_parser_next_token_is (parser, CPP_NAME))
{
- seq_cst = true;
- c_parser_consume_token (parser);
+ const char *p
+ = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ if (!strcmp (p, "seq_cst"))
+ {
+ seq_cst = true;
+ c_parser_consume_token (parser);
+ }
}
}
c_parser_skip_to_pragma_eol (parser);
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index 85df8858dea..53768d619b7 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -612,7 +612,8 @@ extern void push_init_level (int, struct obstack *);
extern struct c_expr pop_init_level (int, struct obstack *);
extern void set_init_index (tree, tree, struct obstack *);
extern void set_init_label (tree, struct obstack *);
-extern void process_init_element (struct c_expr, bool, struct obstack *);
+extern void process_init_element (location_t, struct c_expr, bool,
+ struct obstack *);
extern tree build_compound_literal (location_t, tree, tree, bool);
extern void check_compound_literal_type (location_t, struct c_type_name *);
extern tree c_start_case (location_t, location_t, tree);
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 886ef518be6..e4293104d7b 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -103,8 +103,8 @@ static int spelling_length (void);
static char *print_spelling (char *);
static void warning_init (int, const char *);
static tree digest_init (location_t, tree, tree, tree, bool, bool, int);
-static void output_init_element (tree, tree, bool, tree, tree, int, bool,
- struct obstack *);
+static void output_init_element (location_t, tree, tree, bool, tree, tree, int,
+ bool, struct obstack *);
static void output_pending_init_elements (int, struct obstack *);
static int set_designator (int, struct obstack *);
static void push_range_stack (tree, struct obstack *);
@@ -7182,13 +7182,15 @@ push_init_level (int implicit, struct obstack * braced_init_obstack)
if ((TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
&& constructor_fields == 0)
- process_init_element (pop_init_level (1, braced_init_obstack),
+ process_init_element (input_location,
+ pop_init_level (1, braced_init_obstack),
true, braced_init_obstack);
else if (TREE_CODE (constructor_type) == ARRAY_TYPE
&& constructor_max_index
&& tree_int_cst_lt (constructor_max_index,
constructor_index))
- process_init_element (pop_init_level (1, braced_init_obstack),
+ process_init_element (input_location,
+ pop_init_level (1, braced_init_obstack),
true, braced_init_obstack);
else
break;
@@ -7388,10 +7390,9 @@ pop_init_level (int implicit, struct obstack * braced_init_obstack)
/* When we come to an explicit close brace,
pop any inner levels that didn't have explicit braces. */
while (constructor_stack->implicit)
- {
- process_init_element (pop_init_level (1, braced_init_obstack),
- true, braced_init_obstack);
- }
+ process_init_element (input_location,
+ pop_init_level (1, braced_init_obstack),
+ true, braced_init_obstack);
gcc_assert (!constructor_range_stack);
}
@@ -7569,10 +7570,9 @@ set_designator (int array, struct obstack * braced_init_obstack)
/* Designator list starts at the level of closest explicit
braces. */
while (constructor_stack->implicit)
- {
- process_init_element (pop_init_level (1, braced_init_obstack),
- true, braced_init_obstack);
- }
+ process_init_element (input_location,
+ pop_init_level (1, braced_init_obstack),
+ true, braced_init_obstack);
constructor_designated = 1;
return 0;
}
@@ -8194,9 +8194,9 @@ find_init_member (tree field, struct obstack * braced_init_obstack)
existing initializer. */
static void
-output_init_element (tree value, tree origtype, bool strict_string, tree type,
- tree field, int pending, bool implicit,
- struct obstack * braced_init_obstack)
+output_init_element (location_t loc, tree value, tree origtype,
+ bool strict_string, tree type, tree field, int pending,
+ bool implicit, struct obstack * braced_init_obstack)
{
tree semantic_type = NULL_TREE;
bool maybe_const = true;
@@ -8294,8 +8294,8 @@ output_init_element (tree value, tree origtype, bool strict_string, tree type,
if (semantic_type)
value = build1 (EXCESS_PRECISION_EXPR, semantic_type, value);
- value = digest_init (input_location, type, value, origtype, npc,
- strict_string, require_constant_value);
+ value = digest_init (loc, type, value, origtype, npc, strict_string,
+ require_constant_value);
if (value == error_mark_node)
{
constructor_erroneous = 1;
@@ -8422,8 +8422,8 @@ output_pending_init_elements (int all, struct obstack * braced_init_obstack)
{
if (tree_int_cst_equal (elt->purpose,
constructor_unfilled_index))
- output_init_element (elt->value, elt->origtype, true,
- TREE_TYPE (constructor_type),
+ output_init_element (input_location, elt->value, elt->origtype,
+ true, TREE_TYPE (constructor_type),
constructor_unfilled_index, 0, false,
braced_init_obstack);
else if (tree_int_cst_lt (constructor_unfilled_index,
@@ -8477,8 +8477,8 @@ output_pending_init_elements (int all, struct obstack * braced_init_obstack)
if (tree_int_cst_equal (elt_bitpos, ctor_unfilled_bitpos))
{
constructor_unfilled_fields = elt->purpose;
- output_init_element (elt->value, elt->origtype, true,
- TREE_TYPE (elt->purpose),
+ output_init_element (input_location, elt->value, elt->origtype,
+ true, TREE_TYPE (elt->purpose),
elt->purpose, 0, false,
braced_init_obstack);
}
@@ -8551,7 +8551,7 @@ output_pending_init_elements (int all, struct obstack * braced_init_obstack)
existing initializer. */
void
-process_init_element (struct c_expr value, bool implicit,
+process_init_element (location_t loc, struct c_expr value, bool implicit,
struct obstack * braced_init_obstack)
{
tree orig_value = value.value;
@@ -8595,14 +8595,14 @@ process_init_element (struct c_expr value, bool implicit,
if ((TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
&& constructor_fields == 0)
- process_init_element (pop_init_level (1, braced_init_obstack),
+ process_init_element (loc, pop_init_level (1, braced_init_obstack),
true, braced_init_obstack);
else if ((TREE_CODE (constructor_type) == ARRAY_TYPE
|| TREE_CODE (constructor_type) == VECTOR_TYPE)
&& constructor_max_index
&& tree_int_cst_lt (constructor_max_index,
constructor_index))
- process_init_element (pop_init_level (1, braced_init_obstack),
+ process_init_element (loc, pop_init_level (1, braced_init_obstack),
true, braced_init_obstack);
else
break;
@@ -8680,7 +8680,7 @@ process_init_element (struct c_expr value, bool implicit,
if (value.value)
{
push_member_name (constructor_fields);
- output_init_element (value.value, value.original_type,
+ output_init_element (loc, value.value, value.original_type,
strict_string, fieldtype,
constructor_fields, 1, implicit,
braced_init_obstack);
@@ -8772,7 +8772,7 @@ process_init_element (struct c_expr value, bool implicit,
if (value.value)
{
push_member_name (constructor_fields);
- output_init_element (value.value, value.original_type,
+ output_init_element (loc, value.value, value.original_type,
strict_string, fieldtype,
constructor_fields, 1, implicit,
braced_init_obstack);
@@ -8824,7 +8824,7 @@ process_init_element (struct c_expr value, bool implicit,
if (value.value)
{
push_array_bounds (tree_to_uhwi (constructor_index));
- output_init_element (value.value, value.original_type,
+ output_init_element (loc, value.value, value.original_type,
strict_string, elttype,
constructor_index, 1, implicit,
braced_init_obstack);
@@ -8859,7 +8859,7 @@ process_init_element (struct c_expr value, bool implicit,
{
if (TREE_CODE (value.value) == VECTOR_CST)
elttype = TYPE_MAIN_VARIANT (constructor_type);
- output_init_element (value.value, value.original_type,
+ output_init_element (loc, value.value, value.original_type,
strict_string, elttype,
constructor_index, 1, implicit,
braced_init_obstack);
@@ -8888,7 +8888,7 @@ process_init_element (struct c_expr value, bool implicit,
else
{
if (value.value)
- output_init_element (value.value, value.original_type,
+ output_init_element (loc, value.value, value.original_type,
strict_string, constructor_type,
NULL_TREE, 1, implicit,
braced_init_obstack);
@@ -8907,8 +8907,8 @@ process_init_element (struct c_expr value, bool implicit,
while (constructor_stack != range_stack->stack)
{
gcc_assert (constructor_stack->implicit);
- process_init_element (pop_init_level (1,
- braced_init_obstack),
+ process_init_element (loc,
+ pop_init_level (1, braced_init_obstack),
true, braced_init_obstack);
}
for (p = range_stack;
@@ -8916,7 +8916,8 @@ process_init_element (struct c_expr value, bool implicit,
p = p->prev)
{
gcc_assert (constructor_stack->implicit);
- process_init_element (pop_init_level (1, braced_init_obstack),
+ process_init_element (loc,
+ pop_init_level (1, braced_init_obstack),
true, braced_init_obstack);
}
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index 28524f85ca1..b5df572d039 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -1695,8 +1695,8 @@ release_function_body (tree decl)
}
if (cfun->cfg)
{
- gcc_assert (dom_computed[0] == DOM_NONE);
- gcc_assert (dom_computed[1] == DOM_NONE);
+ free_dominance_info (CDI_DOMINATORS);
+ free_dominance_info (CDI_POST_DOMINATORS);
clear_edges ();
cfun->cfg = NULL;
}
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 7bf9a07cbb2..d06ce3217fd 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -520,7 +520,7 @@ cgraph_add_new_function (tree fndecl, bool lowered)
push_cfun (DECL_STRUCT_FUNCTION (fndecl));
gimple_register_cfg_hooks ();
bitmap_obstack_initialize (NULL);
- execute_pass_list (passes->all_lowering_passes);
+ execute_pass_list (cfun, passes->all_lowering_passes);
passes->execute_early_local_passes ();
bitmap_obstack_release (NULL);
pop_cfun ();
@@ -658,7 +658,7 @@ analyze_function (struct cgraph_node *node)
gimple_register_cfg_hooks ();
bitmap_obstack_initialize (NULL);
- execute_pass_list (g->get_passes ()->all_lowering_passes);
+ execute_pass_list (cfun, g->get_passes ()->all_lowering_passes);
free_dominance_info (CDI_POST_DOMINATORS);
free_dominance_info (CDI_DOMINATORS);
compact_blocks ();
@@ -1771,7 +1771,7 @@ expand_function (struct cgraph_node *node)
/* Signal the start of passes. */
invoke_plugin_callbacks (PLUGIN_ALL_PASSES_START, NULL);
- execute_pass_list (g->get_passes ()->all_passes);
+ execute_pass_list (cfun, g->get_passes ()->all_passes);
/* Signal the end of passes. */
invoke_plugin_callbacks (PLUGIN_ALL_PASSES_END, NULL);
diff --git a/gcc/config.in b/gcc/config.in
index af02866dd33..c0ba36ea98b 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -172,6 +172,12 @@
#endif
+/* Define to get calls to the valgrind runtime enabled. */
+#ifndef USED_FOR_TARGET
+#undef ENABLE_VALGRIND_ANNOTATIONS
+#endif
+
+
/* Define if you want to run subprograms and generated programs through
valgrind (a memory checker). This is extremely expensive. */
#ifndef USED_FOR_TARGET
@@ -1697,12 +1703,6 @@
#endif
-/* Define to the library containing __tls_get_addr/___tls_get_addr. */
-#ifndef USED_FOR_TARGET
-#undef LIB_TLS_SPEC
-#endif
-
-
/* The linker hash style */
#ifndef USED_FOR_TARGET
#undef LINKER_HASH_STYLE
diff --git a/gcc/config/arm/aarch-common.c b/gcc/config/arm/aarch-common.c
index 884d4b37fac..d31191ab9e7 100644
--- a/gcc/config/arm/aarch-common.c
+++ b/gcc/config/arm/aarch-common.c
@@ -195,14 +195,18 @@ bool
aarch_rev16_shright_mask_imm_p (rtx val, enum machine_mode mode)
{
return CONST_INT_P (val)
- && INTVAL (val) == trunc_int_for_mode (0xff00ff00ff00ff, mode);
+ && INTVAL (val)
+ == trunc_int_for_mode (HOST_WIDE_INT_C (0xff00ff00ff00ff),
+ mode);
}
bool
aarch_rev16_shleft_mask_imm_p (rtx val, enum machine_mode mode)
{
return CONST_INT_P (val)
- && INTVAL (val) == trunc_int_for_mode (0xff00ff00ff00ff00, mode);
+ && INTVAL (val)
+ == trunc_int_for_mode (HOST_WIDE_INT_C (0xff00ff00ff00ff00),
+ mode);
}
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 8ca945f1a67..1e44080d601 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -1710,7 +1710,8 @@ const struct tune_params arm_cortex_a8_tune =
false, /* Prefer LDRD/STRD. */
{true, true}, /* Prefer non short circuit. */
&arm_default_vec_cost, /* Vectorizer costs. */
- false /* Prefer Neon for 64-bits bitops. */
+ false, /* Prefer Neon for 64-bits bitops. */
+ false, false /* Prefer 32-bit encodings. */
};
const struct tune_params arm_cortex_a7_tune =
@@ -6216,11 +6217,6 @@ arm_function_ok_for_sibcall (tree decl, tree exp)
if (TARGET_VXWORKS_RTP && flag_pic && !targetm.binds_local_p (decl))
return false;
- /* Cannot tail-call to long calls, since these are out of range of
- a branch instruction. */
- if (decl && arm_is_long_call_p (decl))
- return false;
-
/* If we are interworking and the function is not declared static
then we can't tail-call it unless we know that it exists in this
compilation unit (since it might be a Thumb routine). */
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 8a949b929fa..97753ce1e98 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -9367,8 +9367,10 @@
"TARGET_32BIT"
"
{
- if (!REG_P (XEXP (operands[0], 0))
- && (GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF))
+ if ((!REG_P (XEXP (operands[0], 0))
+ && GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF)
+ || (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
+ && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[0], 0)))))
XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
if (operands[2] == NULL_RTX)
@@ -9385,8 +9387,10 @@
"TARGET_32BIT"
"
{
- if (!REG_P (XEXP (operands[1], 0)) &&
- (GET_CODE (XEXP (operands[1],0)) != SYMBOL_REF))
+ if ((!REG_P (XEXP (operands[1], 0))
+ && GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF)
+ || (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
+ && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[1], 0)))))
XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
if (operands[3] == NULL_RTX)
diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md
index 6273e8820c6..d74fcb31bc7 100644
--- a/gcc/config/arm/predicates.md
+++ b/gcc/config/arm/predicates.md
@@ -681,5 +681,6 @@
(match_code "reg" "0")))
(define_predicate "call_insn_operand"
- (ior (match_code "symbol_ref")
+ (ior (and (match_code "symbol_ref")
+ (match_test "!arm_is_long_call_p (SYMBOL_REF_DECL (op))"))
(match_operand 0 "s_register_operand")))
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index 25075b2f4b3..0fa7f6633e2 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -290,6 +290,12 @@ avr_to_int_mode (rtx x)
static void
avr_option_override (void)
{
+ /* Disable -fdelete-null-pointer-checks option for AVR target.
+ This option compiler assumes that dereferencing of a null pointer
+ would halt the program. For AVR this assumption is not true and
+ programs can safely dereference null pointers. Changes made by this
+ option may not work properly for AVR. So disable this option. */
+
flag_delete_null_pointer_checks = 0;
/* caller-save.c looks for call-clobbered hard registers that are assigned
diff --git a/gcc/config/i386/i386-c.c b/gcc/config/i386/i386-c.c
index c9977bf2b0e..2c31dc8062d 100644
--- a/gcc/config/i386/i386-c.c
+++ b/gcc/config/i386/i386-c.c
@@ -518,6 +518,13 @@ ix86_target_macros (void)
if (TARGET_LONG_DOUBLE_128)
cpp_define (parse_in, "__LONG_DOUBLE_128__");
+ if (TARGET_128BIT_LONG_DOUBLE)
+ cpp_define (parse_in, "__SIZEOF_FLOAT80__=16");
+ else
+ cpp_define (parse_in, "__SIZEOF_FLOAT80__=12");
+
+ cpp_define (parse_in, "__SIZEOF_FLOAT128__=16");
+
cpp_define_formatted (parse_in, "__ATOMIC_HLE_ACQUIRE=%d", IX86_HLE_ACQUIRE);
cpp_define_formatted (parse_in, "__ATOMIC_HLE_RELEASE=%d", IX86_HLE_RELEASE);
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 25e2e93e317..fde0a93e68f 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -3201,7 +3201,7 @@
(const_string "1")
(const_string "*")))
(set (attr "mode")
- (cond [(eq_attr "alternative" "3,4,9,10,13,14,15")
+ (cond [(eq_attr "alternative" "3,4,9,10,12,13,14,15")
(const_string "SI")
(eq_attr "alternative" "11")
(const_string "DI")
@@ -14427,15 +14427,16 @@
"TARGET_USE_FANCY_MATH_387
&& flag_unsafe_math_optimizations"
{
+ rtx tmp1, tmp2;
if (optimize_insn_for_size_p ())
FAIL;
- operands[3] = gen_reg_rtx (XFmode);
- operands[4] = gen_reg_rtx (XFmode);
+ tmp1 = gen_reg_rtx (XFmode);
+ tmp2 = gen_reg_rtx (XFmode);
- emit_insn (gen_floatsixf2 (operands[3], operands[2]));
- emit_insn (gen_fscalexf4_i387 (operands[0], operands[4],
- operands[1], operands[3]));
+ emit_insn (gen_floatsixf2 (tmp1, operands[2]));
+ emit_insn (gen_fscalexf4_i387 (operands[0], tmp2,
+ operands[1], tmp1));
DONE;
})
diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md
index e61048b4d0b..72c11f592db 100644
--- a/gcc/config/m68k/m68k.md
+++ b/gcc/config/m68k/m68k.md
@@ -1868,9 +1868,11 @@
;; Maybe there is a way to make that the general case, by forcing the
;; result of the SI tree to be in the lower register of the DI target
+;; Don't allow memory for operand 1 as that would require an earlyclobber
+;; which results in worse code
(define_insn "extendplussidi"
[(set (match_operand:DI 0 "register_operand" "=d")
- (sign_extend:DI (plus:SI (match_operand:SI 1 "general_operand" "%rmn")
+ (sign_extend:DI (plus:SI (match_operand:SI 1 "general_operand" "%rn")
(match_operand:SI 2 "general_operand" "rmn"))))]
""
{
diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md
index 674cb40bf7a..a8cfcb739ea 100644
--- a/gcc/config/rs6000/altivec.md
+++ b/gcc/config/rs6000/altivec.md
@@ -143,6 +143,9 @@
UNSPEC_VSUBEUQM
UNSPEC_VSUBECUQ
UNSPEC_VBPERMQ
+ UNSPEC_BCDADD
+ UNSPEC_BCDSUB
+ UNSPEC_BCD_OVERFLOW
])
(define_c_enum "unspecv"
@@ -3334,3 +3337,112 @@
"vbpermq %0,%1,%2"
[(set_attr "length" "4")
(set_attr "type" "vecsimple")])
+
+;; Decimal Integer operations
+(define_int_iterator UNSPEC_BCD_ADD_SUB [UNSPEC_BCDADD UNSPEC_BCDSUB])
+
+(define_int_attr bcd_add_sub [(UNSPEC_BCDADD "add")
+ (UNSPEC_BCDSUB "sub")])
+
+(define_code_iterator BCD_TEST [eq lt gt unordered])
+
+(define_insn "bcd<bcd_add_sub>"
+ [(set (match_operand:V1TI 0 "register_operand" "")
+ (unspec:V1TI [(match_operand:V1TI 1 "register_operand" "")
+ (match_operand:V1TI 2 "register_operand" "")
+ (match_operand:QI 3 "const_0_to_1_operand" "")]
+ UNSPEC_BCD_ADD_SUB))
+ (clobber (reg:CCFP 74))]
+ "TARGET_P8_VECTOR"
+ "bcd<bcd_add_sub>. %0,%1,%2,%3"
+ [(set_attr "length" "4")
+ (set_attr "type" "vecsimple")])
+
+;; Use a floating point type (V2DFmode) for the compare to set CR6 so that we
+;; can use the unordered test for BCD nans and add/subtracts that overflow. An
+;; UNORDERED test on an integer type (like V1TImode) is not defined. The type
+;; probably should be one that can go in the VMX (Altivec) registers, so we
+;; can't use DDmode or DFmode.
+(define_insn "*bcd<bcd_add_sub>_test"
+ [(set (reg:CCFP 74)
+ (compare:CCFP
+ (unspec:V2DF [(match_operand:V1TI 1 "register_operand" "v")
+ (match_operand:V1TI 2 "register_operand" "v")
+ (match_operand:QI 3 "const_0_to_1_operand" "i")]
+ UNSPEC_BCD_ADD_SUB)
+ (match_operand:V2DF 4 "zero_constant" "j")))
+ (clobber (match_scratch:V1TI 0 "=v"))]
+ "TARGET_P8_VECTOR"
+ "bcd<bcd_add_sub>. %0,%1,%2,%3"
+ [(set_attr "length" "4")
+ (set_attr "type" "vecsimple")])
+
+(define_insn "*bcd<bcd_add_sub>_test2"
+ [(set (match_operand:V1TI 0 "register_operand" "=v")
+ (unspec:V1TI [(match_operand:V1TI 1 "register_operand" "v")
+ (match_operand:V1TI 2 "register_operand" "v")
+ (match_operand:QI 3 "const_0_to_1_operand" "i")]
+ UNSPEC_BCD_ADD_SUB))
+ (set (reg:CCFP 74)
+ (compare:CCFP
+ (unspec:V2DF [(match_dup 1)
+ (match_dup 2)
+ (match_dup 3)]
+ UNSPEC_BCD_ADD_SUB)
+ (match_operand:V2DF 4 "zero_constant" "j")))]
+ "TARGET_P8_VECTOR"
+ "bcd<bcd_add_sub>. %0,%1,%2,%3"
+ [(set_attr "length" "4")
+ (set_attr "type" "vecsimple")])
+
+(define_expand "bcd<bcd_add_sub>_<code>"
+ [(parallel [(set (reg:CCFP 74)
+ (compare:CCFP
+ (unspec:V2DF [(match_operand:V1TI 1 "register_operand" "")
+ (match_operand:V1TI 2 "register_operand" "")
+ (match_operand:QI 3 "const_0_to_1_operand" "")]
+ UNSPEC_BCD_ADD_SUB)
+ (match_dup 4)))
+ (clobber (match_scratch:V1TI 5 ""))])
+ (set (match_operand:SI 0 "register_operand" "")
+ (BCD_TEST:SI (reg:CCFP 74)
+ (const_int 0)))]
+ "TARGET_P8_VECTOR"
+{
+ operands[4] = CONST0_RTX (V2DFmode);
+})
+
+;; Peephole2 pattern to combine a bcdadd/bcdsub that calculates the value and
+;; the bcdadd/bcdsub that tests the value. The combiner won't work since
+;; CR6 is a hard coded register. Unfortunately, all of the Altivec predicate
+;; support is hard coded to use the fixed register CR6 instead of creating
+;; a register class for CR6.
+
+(define_peephole2
+ [(parallel [(set (match_operand:V1TI 0 "register_operand" "")
+ (unspec:V1TI [(match_operand:V1TI 1 "register_operand" "")
+ (match_operand:V1TI 2 "register_operand" "")
+ (match_operand:QI 3 "const_0_to_1_operand" "")]
+ UNSPEC_BCD_ADD_SUB))
+ (clobber (reg:CCFP 74))])
+ (parallel [(set (reg:CCFP 74)
+ (compare:CCFP
+ (unspec:V2DF [(match_dup 1)
+ (match_dup 2)
+ (match_dup 3)]
+ UNSPEC_BCD_ADD_SUB)
+ (match_operand:V2DF 4 "zero_constant" "")))
+ (clobber (match_operand:V1TI 5 "register_operand" ""))])]
+ "TARGET_P8_VECTOR"
+ [(parallel [(set (match_dup 0)
+ (unspec:V1TI [(match_dup 1)
+ (match_dup 2)
+ (match_dup 3)]
+ UNSPEC_BCD_ADD_SUB))
+ (set (reg:CCFP 74)
+ (compare:CCFP
+ (unspec:V2DF [(match_dup 1)
+ (match_dup 2)
+ (match_dup 3)]
+ UNSPEC_BCD_ADD_SUB)
+ (match_dup 4)))])])
diff --git a/gcc/config/rs6000/dfp.md b/gcc/config/rs6000/dfp.md
index 8e99bc0d787..40e27e77d23 100644
--- a/gcc/config/rs6000/dfp.md
+++ b/gcc/config/rs6000/dfp.md
@@ -322,3 +322,72 @@
"TARGET_DFP"
"dctfixq %0,%1"
[(set_attr "type" "fp")])
+
+
+;; Decimal builtin support
+
+(define_c_enum "unspec"
+ [UNSPEC_DDEDPD
+ UNSPEC_DENBCD
+ UNSPEC_DXEX
+ UNSPEC_DIEX
+ UNSPEC_DSCLI
+ UNSPEC_DSCRI])
+
+(define_mode_iterator D64_D128 [DD TD])
+
+(define_mode_attr dfp_suffix [(DD "")
+ (TD "q")])
+
+(define_insn "dfp_ddedpd_<mode>"
+ [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
+ (unspec:D64_D128 [(match_operand:QI 1 "const_0_to_3_operand" "i")
+ (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
+ UNSPEC_DDEDPD))]
+ "TARGET_DFP"
+ "ddedpd<dfp_suffix> %1,%0,%2"
+ [(set_attr "type" "fp")])
+
+(define_insn "dfp_denbcd_<mode>"
+ [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
+ (unspec:D64_D128 [(match_operand:QI 1 "const_0_to_1_operand" "i")
+ (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
+ UNSPEC_DENBCD))]
+ "TARGET_DFP"
+ "denbcd<dfp_suffix> %1,%0,%2"
+ [(set_attr "type" "fp")])
+
+(define_insn "dfp_dxex_<mode>"
+ [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
+ (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")]
+ UNSPEC_DXEX))]
+ "TARGET_DFP"
+ "dxex<dfp_suffix> %0,%1"
+ [(set_attr "type" "fp")])
+
+(define_insn "dfp_diex_<mode>"
+ [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
+ (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")
+ (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
+ UNSPEC_DXEX))]
+ "TARGET_DFP"
+ "diex<dfp_suffix> %0,%1,%2"
+ [(set_attr "type" "fp")])
+
+(define_insn "dfp_dscli_<mode>"
+ [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
+ (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")
+ (match_operand:QI 2 "immediate_operand" "i")]
+ UNSPEC_DSCLI))]
+ "TARGET_DFP"
+ "dscli<dfp_suffix> %0,%1,%2"
+ [(set_attr "type" "fp")])
+
+(define_insn "dfp_dscri_<mode>"
+ [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
+ (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")
+ (match_operand:QI 2 "immediate_operand" "i")]
+ UNSPEC_DSCRI))]
+ "TARGET_DFP"
+ "dscri<dfp_suffix> %0,%1,%2"
+ [(set_attr "type" "fp")])
diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index 2ed1d4a184d..1616b888c9c 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -171,6 +171,11 @@
(and (match_code "const_int")
(match_test "IN_RANGE (INTVAL (op), 0, 1)")))
+;; Match op = 0..3.
+(define_predicate "const_0_to_3_operand"
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (INTVAL (op), 0, 3)")))
+
;; Match op = 2 or op = 3.
(define_predicate "const_2_to_3_operand"
(and (match_code "const_int")
diff --git a/gcc/config/rs6000/rs6000-builtin.def b/gcc/config/rs6000/rs6000-builtin.def
index 83351691fa5..16793f501e7 100644
--- a/gcc/config/rs6000/rs6000-builtin.def
+++ b/gcc/config/rs6000/rs6000-builtin.def
@@ -570,6 +570,75 @@
MASK, /* MASK */ \
(ATTR | RS6000_BTC_SPECIAL), /* ATTR */ \
CODE_FOR_nothing) /* ICODE */
+
+
+/* Decimal floating point builtins for instructions. */
+#define BU_DFP_MISC_1(ENUM, NAME, ATTR, ICODE) \
+ RS6000_BUILTIN_1 (MISC_BUILTIN_ ## ENUM, /* ENUM */ \
+ "__builtin_" NAME, /* NAME */ \
+ RS6000_BTM_DFP, /* MASK */ \
+ (RS6000_BTC_ ## ATTR /* ATTR */ \
+ | RS6000_BTC_UNARY), \
+ CODE_FOR_ ## ICODE) /* ICODE */
+
+#define BU_DFP_MISC_2(ENUM, NAME, ATTR, ICODE) \
+ RS6000_BUILTIN_2 (MISC_BUILTIN_ ## ENUM, /* ENUM */ \
+ "__builtin_" NAME, /* NAME */ \
+ RS6000_BTM_DFP, /* MASK */ \
+ (RS6000_BTC_ ## ATTR /* ATTR */ \
+ | RS6000_BTC_BINARY), \
+ CODE_FOR_ ## ICODE) /* ICODE */
+
+
+/* Miscellaneous builtins for instructions added in ISA 2.06. These
+ instructions don't require either the DFP or VSX options, just the basic ISA
+ 2.06 (popcntd) enablement since they operate on general purpose
+ registers. */
+#define BU_P7_MISC_1(ENUM, NAME, ATTR, ICODE) \
+ RS6000_BUILTIN_1 (MISC_BUILTIN_ ## ENUM, /* ENUM */ \
+ "__builtin_" NAME, /* NAME */ \
+ RS6000_BTM_POPCNTD, /* MASK */ \
+ (RS6000_BTC_ ## ATTR /* ATTR */ \
+ | RS6000_BTC_UNARY), \
+ CODE_FOR_ ## ICODE) /* ICODE */
+
+#define BU_P7_MISC_2(ENUM, NAME, ATTR, ICODE) \
+ RS6000_BUILTIN_2 (MISC_BUILTIN_ ## ENUM, /* ENUM */ \
+ "__builtin_" NAME, /* NAME */ \
+ RS6000_BTM_POPCNTD, /* MASK */ \
+ (RS6000_BTC_ ## ATTR /* ATTR */ \
+ | RS6000_BTC_BINARY), \
+ CODE_FOR_ ## ICODE) /* ICODE */
+
+
+/* Miscellaneous builtins for instructions added in ISA 2.07. These
+ instructions do require the ISA 2.07 vector support, but they aren't vector
+ instructions. */
+#define BU_P8V_MISC_3(ENUM, NAME, ATTR, ICODE) \
+ RS6000_BUILTIN_3 (MISC_BUILTIN_ ## ENUM, /* ENUM */ \
+ "__builtin_" NAME, /* NAME */ \
+ RS6000_BTM_P8_VECTOR, /* MASK */ \
+ (RS6000_BTC_ ## ATTR /* ATTR */ \
+ | RS6000_BTC_TERNARY), \
+ CODE_FOR_ ## ICODE) /* ICODE */
+
+/* Miscellaneous builtins. */
+#define BU_MISC_1(ENUM, NAME, ATTR, ICODE) \
+ RS6000_BUILTIN_2 (MISC_BUILTIN_ ## ENUM, /* ENUM */ \
+ "__builtin_" NAME, /* NAME */ \
+ RS6000_BTM_ALWAYS, /* MASK */ \
+ (RS6000_BTC_ ## ATTR /* ATTR */ \
+ | RS6000_BTC_UNARY), \
+ CODE_FOR_ ## ICODE) /* ICODE */
+
+#define BU_MISC_2(ENUM, NAME, ATTR, ICODE) \
+ RS6000_BUILTIN_2 (MISC_BUILTIN_ ## ENUM, /* ENUM */ \
+ "__builtin_" NAME, /* NAME */ \
+ RS6000_BTM_ALWAYS, /* MASK */ \
+ (RS6000_BTC_ ## ATTR /* ATTR */ \
+ | RS6000_BTC_BINARY), \
+ CODE_FOR_ ## ICODE) /* ICODE */
+
#endif
/* Insure 0 is not a legitimate index. */
@@ -1412,10 +1481,10 @@ BU_P8V_AV_2 (ORC_V4SF, "orc_v4sf", CONST, orcv4sf3)
BU_P8V_AV_2 (ORC_V2DF, "orc_v2df", CONST, orcv2df3)
/* 3 argument altivec instructions added in ISA 2.07. */
-BU_P8V_AV_3 (VADDEUQM, "vaddeuqm", CONST, altivec_vaddeuqm)
-BU_P8V_AV_3 (VADDECUQ, "vaddecuq", CONST, altivec_vaddecuq)
-BU_P8V_AV_3 (VSUBEUQM, "vsubeuqm", CONST, altivec_vsubeuqm)
-BU_P8V_AV_3 (VSUBECUQ, "vsubecuq", CONST, altivec_vsubecuq)
+BU_P8V_AV_3 (VADDEUQM, "vaddeuqm", CONST, altivec_vaddeuqm)
+BU_P8V_AV_3 (VADDECUQ, "vaddecuq", CONST, altivec_vaddecuq)
+BU_P8V_AV_3 (VSUBEUQM, "vsubeuqm", CONST, altivec_vsubeuqm)
+BU_P8V_AV_3 (VSUBECUQ, "vsubecuq", CONST, altivec_vsubecuq)
/* Vector comparison instructions added in ISA 2.07. */
BU_P8V_AV_2 (VCMPEQUD, "vcmpequd", CONST, vector_eqv2di)
@@ -1475,6 +1544,64 @@ BU_P8V_OVERLOAD_3 (VSUBECUQ, "vsubecuq")
BU_P8V_OVERLOAD_3 (VSUBEUQM, "vsubeuqm")
+/* 2 argument extended divide functions added in ISA 2.06. */
+BU_P7_MISC_2 (DIVWE, "divwe", CONST, dive_si)
+BU_P7_MISC_2 (DIVWEO, "divweo", CONST, diveo_si)
+BU_P7_MISC_2 (DIVWEU, "divweu", CONST, diveu_si)
+BU_P7_MISC_2 (DIVWEUO, "divweuo", CONST, diveuo_si)
+BU_P7_MISC_2 (DIVDE, "divde", CONST, dive_di)
+BU_P7_MISC_2 (DIVDEO, "divdeo", CONST, diveo_di)
+BU_P7_MISC_2 (DIVDEU, "divdeu", CONST, diveu_di)
+BU_P7_MISC_2 (DIVDEUO, "divdeuo", CONST, diveuo_di)
+
+/* 1 argument DFP (decimal floating point) functions added in ISA 2.05. */
+BU_DFP_MISC_1 (DXEX, "dxex", CONST, dfp_dxex_dd)
+BU_DFP_MISC_1 (DXEXQ, "dxexq", CONST, dfp_dxex_td)
+
+/* 2 argument DFP (decimal floating point) functions added in ISA 2.05. */
+BU_DFP_MISC_2 (DDEDPD, "ddedpd", CONST, dfp_ddedpd_dd)
+BU_DFP_MISC_2 (DDEDPDQ, "ddedpdq", CONST, dfp_ddedpd_td)
+BU_DFP_MISC_2 (DENBCD, "denbcd", CONST, dfp_denbcd_dd)
+BU_DFP_MISC_2 (DENBCDQ, "denbcdq", CONST, dfp_denbcd_td)
+BU_DFP_MISC_2 (DIEX, "diex", CONST, dfp_diex_dd)
+BU_DFP_MISC_2 (DIEXQ, "diexq", CONST, dfp_diex_td)
+BU_DFP_MISC_2 (DSCLI, "dscli", CONST, dfp_dscli_dd)
+BU_DFP_MISC_2 (DSCLIQ, "dscliq", CONST, dfp_dscli_td)
+BU_DFP_MISC_2 (DSCRI, "dscri", CONST, dfp_dscri_dd)
+BU_DFP_MISC_2 (DSCRIQ, "dscriq", CONST, dfp_dscri_td)
+
+/* 1 argument BCD functions added in ISA 2.06. */
+BU_P7_MISC_1 (CDTBCD, "cdtbcd", CONST, cdtbcd)
+BU_P7_MISC_1 (CBCDTD, "cbcdtd", CONST, cbcdtd)
+
+/* 2 argument BCD functions added in ISA 2.06. */
+BU_P7_MISC_2 (ADDG6S, "addg6s", CONST, addg6s)
+
+/* 3 argument BCD functions added in ISA 2.07. */
+BU_P8V_MISC_3 (BCDADD, "bcdadd", CONST, bcdadd)
+BU_P8V_MISC_3 (BCDADD_LT, "bcdadd_lt", CONST, bcdadd_lt)
+BU_P8V_MISC_3 (BCDADD_EQ, "bcdadd_eq", CONST, bcdadd_eq)
+BU_P8V_MISC_3 (BCDADD_GT, "bcdadd_gt", CONST, bcdadd_gt)
+BU_P8V_MISC_3 (BCDADD_OV, "bcdadd_ov", CONST, bcdadd_unordered)
+BU_P8V_MISC_3 (BCDSUB, "bcdsub", CONST, bcdsub)
+BU_P8V_MISC_3 (BCDSUB_LT, "bcdsub_lt", CONST, bcdsub_lt)
+BU_P8V_MISC_3 (BCDSUB_EQ, "bcdsub_eq", CONST, bcdsub_eq)
+BU_P8V_MISC_3 (BCDSUB_GT, "bcdsub_gt", CONST, bcdsub_gt)
+BU_P8V_MISC_3 (BCDSUB_OV, "bcdsub_ov", CONST, bcdsub_unordered)
+
+/* 2 argument pack/unpack 128-bit floating point types. */
+BU_DFP_MISC_2 (PACK_TD, "pack_dec128", CONST, packtd)
+BU_DFP_MISC_2 (UNPACK_TD, "unpack_dec128", CONST, unpacktd)
+
+BU_MISC_2 (PACK_TF, "pack_longdouble", CONST, packtf)
+BU_MISC_2 (UNPACK_TF, "unpack_longdouble", CONST, unpacktf)
+BU_MISC_1 (UNPACK_TF_0, "longdouble_dw0", CONST, unpacktf_0)
+BU_MISC_1 (UNPACK_TF_1, "longdouble_dw1", CONST, unpacktf_1)
+
+BU_P7_MISC_2 (PACK_V1TI, "pack_vector_int128", CONST, packv1ti)
+BU_P7_MISC_2 (UNPACK_V1TI, "unpack_vector_int128", CONST, unpackv1ti)
+
+
/* 1 argument crypto functions. */
BU_CRYPTO_1 (VSBOX, "vsbox", CONST, crypto_vsbox)
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index bab79df7760..0c983f9a105 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -3038,7 +3038,8 @@ rs6000_builtin_mask_calculate (void)
| ((rs6000_cpu == PROCESSOR_CELL) ? RS6000_BTM_CELL : 0)
| ((TARGET_P8_VECTOR) ? RS6000_BTM_P8_VECTOR : 0)
| ((TARGET_CRYPTO) ? RS6000_BTM_CRYPTO : 0)
- | ((TARGET_HTM) ? RS6000_BTM_HTM : 0));
+ | ((TARGET_HTM) ? RS6000_BTM_HTM : 0)
+ | ((TARGET_DFP) ? RS6000_BTM_DFP : 0));
}
/* Override command line options. Mostly we process the processor type and
@@ -12396,7 +12397,15 @@ rs6000_expand_ternop_builtin (enum insn_code icode, tree exp, rtx target)
}
}
else if (icode == CODE_FOR_vsx_set_v2df
- || icode == CODE_FOR_vsx_set_v2di)
+ || icode == CODE_FOR_vsx_set_v2di
+ || icode == CODE_FOR_bcdadd
+ || icode == CODE_FOR_bcdadd_lt
+ || icode == CODE_FOR_bcdadd_eq
+ || icode == CODE_FOR_bcdadd_gt
+ || icode == CODE_FOR_bcdsub
+ || icode == CODE_FOR_bcdsub_lt
+ || icode == CODE_FOR_bcdsub_eq
+ || icode == CODE_FOR_bcdsub_gt)
{
/* Only allow 1-bit unsigned literals. */
STRIP_NOPS (arg2);
@@ -12407,6 +12416,44 @@ rs6000_expand_ternop_builtin (enum insn_code icode, tree exp, rtx target)
return const0_rtx;
}
}
+ else if (icode == CODE_FOR_dfp_ddedpd_dd
+ || icode == CODE_FOR_dfp_ddedpd_td)
+ {
+ /* Only allow 2-bit unsigned literals where the value is 0 or 2. */
+ STRIP_NOPS (arg0);
+ if (TREE_CODE (arg0) != INTEGER_CST
+ || TREE_INT_CST_LOW (arg2) & ~0x3)
+ {
+ error ("argument 1 must be 0 or 2");
+ return const0_rtx;
+ }
+ }
+ else if (icode == CODE_FOR_dfp_denbcd_dd
+ || icode == CODE_FOR_dfp_denbcd_td)
+ {
+ /* Only allow 1-bit unsigned literals. */
+ STRIP_NOPS (arg0);
+ if (TREE_CODE (arg0) != INTEGER_CST
+ || TREE_INT_CST_LOW (arg0) & ~0x1)
+ {
+ error ("argument 1 must be a 1-bit unsigned literal");
+ return const0_rtx;
+ }
+ }
+ else if (icode == CODE_FOR_dfp_dscli_dd
+ || icode == CODE_FOR_dfp_dscli_td
+ || icode == CODE_FOR_dfp_dscri_dd
+ || icode == CODE_FOR_dfp_dscri_td)
+ {
+ /* Only allow 6-bit unsigned literals. */
+ STRIP_NOPS (arg1);
+ if (TREE_CODE (arg1) != INTEGER_CST
+ || TREE_INT_CST_LOW (arg1) & ~0x3f)
+ {
+ error ("argument 2 must be a 6-bit unsigned literal");
+ return const0_rtx;
+ }
+ }
else if (icode == CODE_FOR_crypto_vshasigmaw
|| icode == CODE_FOR_crypto_vshasigmad)
{
@@ -13496,6 +13543,14 @@ rs6000_invalid_builtin (enum rs6000_builtins fncode)
error ("Builtin function %s requires the -mpaired option", name);
else if ((fnmask & RS6000_BTM_SPE) != 0)
error ("Builtin function %s requires the -mspe option", name);
+ else if ((fnmask & (RS6000_BTM_DFP | RS6000_BTM_P8_VECTOR))
+ == (RS6000_BTM_DFP | RS6000_BTM_P8_VECTOR))
+ error ("Builtin function %s requires the -mhard-dfp and"
+ "-mpower8-vector options", name);
+ else if ((fnmask & RS6000_BTM_DFP) != 0)
+ error ("Builtin function %s requires the -mhard-dfp option", name);
+ else if ((fnmask & RS6000_BTM_P8_VECTOR) != 0)
+ error ("Builtin function %s requires the -mpower8-vector option", name);
else
error ("Builtin function %s is not supported with the current options",
name);
@@ -13775,6 +13830,9 @@ rs6000_init_builtins (void)
uintTI_type_internal_node = unsigned_intTI_type_node;
float_type_internal_node = float_type_node;
double_type_internal_node = double_type_node;
+ long_double_type_internal_node = long_double_type_node;
+ dfloat64_type_internal_node = dfloat64_type_node;
+ dfloat128_type_internal_node = dfloat128_type_node;
void_type_internal_node = void_type_node;
/* Initialize the modes for builtin_function_type, mapping a machine mode to
@@ -13789,6 +13847,9 @@ rs6000_init_builtins (void)
builtin_mode_to_type[TImode][1] = unsigned_intTI_type_node;
builtin_mode_to_type[SFmode][0] = float_type_node;
builtin_mode_to_type[DFmode][0] = double_type_node;
+ builtin_mode_to_type[TFmode][0] = long_double_type_node;
+ builtin_mode_to_type[DDmode][0] = dfloat64_type_node;
+ builtin_mode_to_type[TDmode][0] = dfloat128_type_node;
builtin_mode_to_type[V1TImode][0] = V1TI_type_node;
builtin_mode_to_type[V1TImode][1] = unsigned_V1TI_type_node;
builtin_mode_to_type[V2SImode][0] = V2SI_type_node;
@@ -14881,6 +14942,8 @@ builtin_function_type (enum machine_mode mode_ret, enum machine_mode mode_arg0,
/* unsigned 1 argument functions. */
case CRYPTO_BUILTIN_VSBOX:
case P8V_BUILTIN_VGBBD:
+ case MISC_BUILTIN_CDTBCD:
+ case MISC_BUILTIN_CBCDTD:
h.uns_p[0] = 1;
h.uns_p[1] = 1;
break;
@@ -14899,6 +14962,11 @@ builtin_function_type (enum machine_mode mode_ret, enum machine_mode mode_arg0,
case CRYPTO_BUILTIN_VPMSUMW:
case CRYPTO_BUILTIN_VPMSUMD:
case CRYPTO_BUILTIN_VPMSUM:
+ case MISC_BUILTIN_ADDG6S:
+ case MISC_BUILTIN_DIVWEU:
+ case MISC_BUILTIN_DIVWEUO:
+ case MISC_BUILTIN_DIVDEU:
+ case MISC_BUILTIN_DIVDEUO:
h.uns_p[0] = 1;
h.uns_p[1] = 1;
h.uns_p[2] = 1;
@@ -14960,9 +15028,18 @@ builtin_function_type (enum machine_mode mode_ret, enum machine_mode mode_arg0,
/* signed args, unsigned return. */
case VSX_BUILTIN_XVCVDPUXDS_UNS:
case ALTIVEC_BUILTIN_FIXUNS_V4SF_V4SI:
+ case MISC_BUILTIN_UNPACK_TD:
+ case MISC_BUILTIN_UNPACK_V1TI:
h.uns_p[0] = 1;
break;
+ /* unsigned arguments for 128-bit pack instructions. */
+ case MISC_BUILTIN_PACK_TD:
+ case MISC_BUILTIN_PACK_V1TI:
+ h.uns_p[1] = 1;
+ h.uns_p[2] = 1;
+ break;
+
default:
break;
}
@@ -31226,6 +31303,7 @@ static struct rs6000_opt_mask const rs6000_builtin_mask_names[] =
{ "power8-vector", RS6000_BTM_P8_VECTOR, false, false },
{ "crypto", RS6000_BTM_CRYPTO, false, false },
{ "htm", RS6000_BTM_HTM, false, false },
+ { "hard-dfp", RS6000_BTM_DFP, false, false },
};
/* Option variables that we want to support inside attribute((target)) and
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 9d0d61c74ea..2e677d5936e 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -2516,6 +2516,7 @@ extern int frame_pointer_needed;
#define RS6000_BTM_FRSQRTES MASK_POPCNTB /* FRSQRTES instruction. */
#define RS6000_BTM_POPCNTD MASK_POPCNTD /* Target supports ISA 2.06. */
#define RS6000_BTM_CELL MASK_FPRND /* Target is cell powerpc. */
+#define RS6000_BTM_DFP MASK_DFP /* Decimal floating point. */
#define RS6000_BTM_COMMON (RS6000_BTM_ALTIVEC \
| RS6000_BTM_VSX \
@@ -2527,7 +2528,8 @@ extern int frame_pointer_needed;
| RS6000_BTM_FRSQRTES \
| RS6000_BTM_HTM \
| RS6000_BTM_POPCNTD \
- | RS6000_BTM_CELL)
+ | RS6000_BTM_CELL \
+ | RS6000_BTM_DFP)
/* Define builtin enum index. */
@@ -2622,6 +2624,9 @@ enum rs6000_builtin_type_index
RS6000_BTI_UINTTI, /* unsigned_intTI_type_node */
RS6000_BTI_float, /* float_type_node */
RS6000_BTI_double, /* double_type_node */
+ RS6000_BTI_long_double, /* long_double_type_node */
+ RS6000_BTI_dfloat64, /* dfloat64_type_node */
+ RS6000_BTI_dfloat128, /* dfloat128_type_node */
RS6000_BTI_void, /* void_type_node */
RS6000_BTI_MAX
};
@@ -2673,6 +2678,9 @@ enum rs6000_builtin_type_index
#define uintTI_type_internal_node (rs6000_builtin_types[RS6000_BTI_UINTTI])
#define float_type_internal_node (rs6000_builtin_types[RS6000_BTI_float])
#define double_type_internal_node (rs6000_builtin_types[RS6000_BTI_double])
+#define long_double_type_internal_node (rs6000_builtin_types[RS6000_BTI_long_double])
+#define dfloat64_type_internal_node (rs6000_builtin_types[RS6000_BTI_dfloat64])
+#define dfloat128_type_internal_node (rs6000_builtin_types[RS6000_BTI_dfloat128])
#define void_type_internal_node (rs6000_builtin_types[RS6000_BTI_void])
extern GTY(()) tree rs6000_builtin_types[RS6000_BTI_MAX];
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index cdefc8f78c4..937eabf3727 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -125,6 +125,15 @@
UNSPEC_P8V_MTVSRD
UNSPEC_P8V_XXPERMDI
UNSPEC_P8V_RELOAD_FROM_VSX
+ UNSPEC_ADDG6S
+ UNSPEC_CDTBCD
+ UNSPEC_CBCDTD
+ UNSPEC_DIVE
+ UNSPEC_DIVEO
+ UNSPEC_DIVEU
+ UNSPEC_DIVEUO
+ UNSPEC_UNPACK_128BIT
+ UNSPEC_PACK_128BIT
])
;;
@@ -481,6 +490,10 @@
(V2DF "X,X,X,X,X")
(V1TI "X,X,X,X,X")])
+;; Mode attribute to give the correct type for integer divides
+(define_mode_attr idiv_ldiv [(SI "idiv")
+ (DI "ldiv")])
+
;; Start with fixed-point load and store insns. Here we put only the more
;; complex forms. Basic data transfer is done later.
@@ -2755,10 +2768,7 @@
(match_operand:GPR 2 "gpc_reg_operand" "r")))]
""
"div<wd>u %0,%1,%2"
- [(set (attr "type")
- (cond [(match_operand:SI 0 "" "")
- (const_string "idiv")]
- (const_string "ldiv")))])
+ [(set_attr "type" "<idiv_ldiv>")])
;; For powers of two we can do srai/aze for divide and then adjust for
@@ -2782,10 +2792,7 @@
(match_operand:GPR 2 "gpc_reg_operand" "r")))]
""
"div<wd> %0,%1,%2"
- [(set (attr "type")
- (cond [(match_operand:SI 0 "" "")
- (const_string "idiv")]
- (const_string "ldiv")))])
+ [(set_attr "type" "<idiv_ldiv>")])
(define_expand "mod<mode>3"
[(use (match_operand:GPR 0 "gpc_reg_operand" ""))
@@ -15735,6 +15742,191 @@
})
+;; Miscellaneous ISA 2.06 (power7) instructions
+(define_insn "addg6s"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "register_operand" "r")]
+ UNSPEC_ADDG6S))]
+ "TARGET_POPCNTD"
+ "addg6s %0,%1,%2"
+ [(set_attr "type" "integer")
+ (set_attr "length" "4")])
+
+(define_insn "cdtbcd"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand:SI 1 "register_operand" "r")]
+ UNSPEC_CDTBCD))]
+ "TARGET_POPCNTD"
+ "cdtbcd %0,%1"
+ [(set_attr "type" "integer")
+ (set_attr "length" "4")])
+
+(define_insn "cbcdtd"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand:SI 1 "register_operand" "r")]
+ UNSPEC_CBCDTD))]
+ "TARGET_POPCNTD"
+ "cbcdtd %0,%1"
+ [(set_attr "type" "integer")
+ (set_attr "length" "4")])
+
+(define_int_iterator UNSPEC_DIV_EXTEND [UNSPEC_DIVE
+ UNSPEC_DIVEO
+ UNSPEC_DIVEU
+ UNSPEC_DIVEUO])
+
+(define_int_attr div_extend [(UNSPEC_DIVE "e")
+ (UNSPEC_DIVEO "eo")
+ (UNSPEC_DIVEU "eu")
+ (UNSPEC_DIVEUO "euo")])
+
+(define_insn "div<div_extend>_<mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=r")
+ (unspec:GPR [(match_operand:GPR 1 "register_operand" "r")
+ (match_operand:GPR 2 "register_operand" "r")]
+ UNSPEC_DIV_EXTEND))]
+ "TARGET_POPCNTD"
+ "div<wd><div_extend> %0,%1,%2"
+ [(set_attr "type" "<idiv_ldiv>")])
+
+
+;; Pack/unpack 128-bit floating point types that take 2 scalar registers
+
+; Type of the 64-bit part when packing/unpacking 128-bit floating point types
+(define_mode_attr FP128_64 [(TF "DF") (TD "DI")])
+
+(define_expand "unpack<mode>"
+ [(set (match_operand:<FP128_64> 0 "nonimmediate_operand" "")
+ (unspec:<FP128_64>
+ [(match_operand:FMOVE128 1 "register_operand" "")
+ (match_operand:QI 2 "const_0_to_1_operand" "")]
+ UNSPEC_UNPACK_128BIT))]
+ ""
+ "")
+
+;; The Advance Toolchain 7.0-3 added private builtins: __builtin_longdouble_dw0
+;; and __builtin_longdouble_dw1 to optimize glibc. Add support for these
+;; builtins here.
+
+(define_expand "unpacktf_0"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "")
+ (unspec:DF [(match_operand:TF 1 "register_operand" "")
+ (const_int 0)]
+ UNSPEC_UNPACK_128BIT))]
+ ""
+ "")
+
+(define_expand "unpacktf_1"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "")
+ (unspec:DF [(match_operand:TF 1 "register_operand" "")
+ (const_int 1)]
+ UNSPEC_UNPACK_128BIT))]
+ ""
+ "")
+
+(define_insn_and_split "unpack<mode>_dm"
+ [(set (match_operand:<FP128_64> 0 "nonimmediate_operand" "=d,m,d,r,m")
+ (unspec:<FP128_64>
+ [(match_operand:FMOVE128 1 "register_operand" "d,d,r,d,r")
+ (match_operand:QI 2 "const_0_to_1_operand" "i,i,i,i,i")]
+ UNSPEC_UNPACK_128BIT))]
+ "TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 0) (match_dup 3))]
+{
+ unsigned fp_regno = REGNO (operands[1]) + UINTVAL (operands[2]);
+
+ if (REG_P (operands[0]) && REGNO (operands[0]) == fp_regno)
+ {
+ emit_note (NOTE_INSN_DELETED);
+ DONE;
+ }
+
+ operands[3] = gen_rtx_REG (<FP128_64>mode, fp_regno);
+}
+ [(set_attr "type" "fp,fpstore,mffgpr,mftgpr,store")
+ (set_attr "length" "4")])
+
+(define_insn_and_split "unpack<mode>_nodm"
+ [(set (match_operand:<FP128_64> 0 "nonimmediate_operand" "=d,m")
+ (unspec:<FP128_64>
+ [(match_operand:FMOVE128 1 "register_operand" "d,d")
+ (match_operand:QI 2 "const_0_to_1_operand" "i,i")]
+ UNSPEC_UNPACK_128BIT))]
+ "!TARGET_POWERPC64 || !TARGET_DIRECT_MOVE"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 0) (match_dup 3))]
+{
+ unsigned fp_regno = REGNO (operands[1]) + UINTVAL (operands[2]);
+
+ if (REG_P (operands[0]) && REGNO (operands[0]) == fp_regno)
+ {
+ emit_note (NOTE_INSN_DELETED);
+ DONE;
+ }
+
+ operands[3] = gen_rtx_REG (<FP128_64>mode, fp_regno);
+}
+ [(set_attr "type" "fp,fpstore")
+ (set_attr "length" "4")])
+
+(define_insn_and_split "pack<mode>"
+ [(set (match_operand:FMOVE128 0 "register_operand" "=d,&d")
+ (unspec:FMOVE128
+ [(match_operand:<FP128_64> 1 "register_operand" "0,d")
+ (match_operand:<FP128_64> 2 "register_operand" "d,d")]
+ UNSPEC_PACK_128BIT))]
+ ""
+ "@
+ fmr %L0,%2
+ #"
+ "&& reload_completed && REGNO (operands[0]) != REGNO (operands[1])"
+ [(set (match_dup 3) (match_dup 1))
+ (set (match_dup 4) (match_dup 2))]
+{
+ unsigned dest_hi = REGNO (operands[0]);
+ unsigned dest_lo = dest_hi + 1;
+
+ gcc_assert (!IN_RANGE (REGNO (operands[1]), dest_hi, dest_lo));
+ gcc_assert (!IN_RANGE (REGNO (operands[2]), dest_hi, dest_lo));
+
+ operands[3] = gen_rtx_REG (<FP128_64>mode, dest_hi);
+ operands[4] = gen_rtx_REG (<FP128_64>mode, dest_lo);
+}
+ [(set_attr "type" "fp,fp")
+ (set_attr "length" "4,8")])
+
+(define_insn "unpackv1ti"
+ [(set (match_operand:DI 0 "register_operand" "=d,d")
+ (unspec:DI [(match_operand:V1TI 1 "register_operand" "0,wa")
+ (match_operand:QI 2 "const_0_to_1_operand" "O,i")]
+ UNSPEC_UNPACK_128BIT))]
+ "TARGET_VSX"
+{
+ if (REGNO (operands[0]) == REGNO (operands[1]) && INTVAL (operands[2]) == 0)
+ return ASM_COMMENT_START " xxpermdi to same register";
+
+ operands[3] = GEN_INT (INTVAL (operands[2]) == 0 ? 0 : 3);
+ return "xxpermdi %x0,%x1,%x1,%3";
+}
+ [(set_attr "type" "vecperm")
+ (set_attr "length" "4")])
+
+(define_insn "packv1ti"
+ [(set (match_operand:V1TI 0 "register_operand" "=wa")
+ (unspec:V1TI
+ [(match_operand:DI 1 "register_operand" "d")
+ (match_operand:DI 2 "register_operand" "d")]
+ UNSPEC_PACK_128BIT))]
+ "TARGET_VSX"
+ "xxpermdi %x0,%x1,%x2,0"
+ [(set_attr "type" "vecperm")
+ (set_attr "length" "4")])
+
+
(include "sync.md")
(include "vector.md")
diff --git a/gcc/config/sol2.h b/gcc/config/sol2.h
index 2a657db59c1..a21c953b035 100644
--- a/gcc/config/sol2.h
+++ b/gcc/config/sol2.h
@@ -115,7 +115,6 @@ along with GCC; see the file COPYING3. If not see
#define LIB_SPEC \
"%{!symbolic:\
%{pthreads|pthread:-lpthread} \
- %{pthreads|pthread|fprofile-generate*:" LIB_TLS_SPEC "} \
%{p|pg:-ldl} -lc}"
#ifndef CROSS_DIRECTORY_STRUCTURE
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index 8b6c647fc00..e2a4669e05d 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -5795,19 +5795,6 @@
}
[(set_attr "type" "shift")])
-(define_insn "*ashlsi3_extend"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (zero_extend:DI
- (ashift:SI (match_operand:SI 1 "register_operand" "r")
- (match_operand:SI 2 "arith_operand" "rI"))))]
- "TARGET_ARCH64"
-{
- if (GET_CODE (operands[2]) == CONST_INT)
- operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
- return "sll\t%1, %2, %0";
-}
- [(set_attr "type" "shift")])
-
(define_expand "ashldi3"
[(set (match_operand:DI 0 "register_operand" "=r")
(ashift:DI (match_operand:DI 1 "register_operand" "r")
diff --git a/gcc/config/sparc/sparc.opt b/gcc/config/sparc/sparc.opt
index c02aec59f06..64e40955a53 100644
--- a/gcc/config/sparc/sparc.opt
+++ b/gcc/config/sparc/sparc.opt
@@ -113,6 +113,10 @@ mrelax
Target
Optimize tail call instructions in assembler and linker
+muser-mode
+Target Report Mask(USER_MODE)
+Do not generate code that can only run in supervisor mode
+
mcpu=
Target RejectNegative Joined Var(sparc_cpu_and_features) Enum(sparc_processor_type) Init(PROCESSOR_V7)
Use features of and schedule code for given CPU
diff --git a/gcc/config/sparc/sync.md b/gcc/config/sparc/sync.md
index fd5691f73be..e6e237f256f 100644
--- a/gcc/config/sparc/sync.md
+++ b/gcc/config/sparc/sync.md
@@ -200,10 +200,27 @@
[(match_operand:I48MODE 2 "register_operand" "r")
(match_operand:I48MODE 3 "register_operand" "0")]
UNSPECV_CAS))]
- "(TARGET_V9 || TARGET_LEON3) && (<MODE>mode != DImode || TARGET_ARCH64)"
+ "TARGET_V9 && (<MODE>mode != DImode || TARGET_ARCH64)"
"cas<modesuffix>\t%1, %2, %0"
[(set_attr "type" "multi")])
+(define_insn "*atomic_compare_and_swap_leon3_1"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (match_operand:SI 1 "mem_noofs_operand" "+w"))
+ (set (match_dup 1)
+ (unspec_volatile:SI
+ [(match_operand:SI 2 "register_operand" "r")
+ (match_operand:SI 3 "register_operand" "0")]
+ UNSPECV_CAS))]
+ "TARGET_LEON3"
+{
+ if (TARGET_USER_MODE)
+ return "casa\t%1 0xa, %2, %0"; /* ASI for user data space. */
+ else
+ return "casa\t%1 0xb, %2, %0"; /* ASI for supervisor data space. */
+}
+ [(set_attr "type" "multi")])
+
(define_insn "*atomic_compare_and_swapdi_v8plus"
[(set (match_operand:DI 0 "register_operand" "=h")
(match_operand:DI 1 "mem_noofs_operand" "+w"))
diff --git a/gcc/configure b/gcc/configure
index 813ccce2257..d912261c1cf 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -882,6 +882,7 @@ enable_werror_always
enable_checking
enable_coverage
enable_gather_detailed_mem_stats
+enable_valgrind_annotations
with_stabs
enable_multilib
enable_multiarch
@@ -1591,6 +1592,8 @@ Optional Features:
Values are opt, noopt, default is noopt
--enable-gather-detailed-mem-stats
enable detailed memory allocation stats gathering
+ --enable-valgrind-annotations
+ enable valgrind runtime interaction
--enable-multilib enable library support for multiple ABIs
--enable-multiarch enable support for multiarch paths
--enable-__cxa_atexit enable __cxa_atexit for C++
@@ -6772,12 +6775,11 @@ fi
-if test x$ac_valgrind_checking != x ; then
- # It is certainly possible that there's valgrind but no valgrind.h.
- # GCC relies on making annotations so we must have both.
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for VALGRIND_DISCARD in <valgrind/memcheck.h>" >&5
+# It is certainly possible that there's valgrind but no valgrind.h.
+# GCC relies on making annotations so we must have both.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for VALGRIND_DISCARD in <valgrind/memcheck.h>" >&5
$as_echo_n "checking for VALGRIND_DISCARD in <valgrind/memcheck.h>... " >&6; }
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <valgrind/memcheck.h>
#ifndef VALGRIND_DISCARD
@@ -6790,11 +6792,11 @@ else
gcc_cv_header_valgrind_memcheck_h=no
fi
rm -f conftest.err conftest.$ac_ext
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_header_valgrind_memcheck_h" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_header_valgrind_memcheck_h" >&5
$as_echo "$gcc_cv_header_valgrind_memcheck_h" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for VALGRIND_DISCARD in <memcheck.h>" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for VALGRIND_DISCARD in <memcheck.h>" >&5
$as_echo_n "checking for VALGRIND_DISCARD in <memcheck.h>... " >&6; }
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <memcheck.h>
#ifndef VALGRIND_DISCARD
@@ -6807,8 +6809,20 @@ else
gcc_cv_header_memcheck_h=no
fi
rm -f conftest.err conftest.$ac_ext
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_header_memcheck_h" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_header_memcheck_h" >&5
$as_echo "$gcc_cv_header_memcheck_h" >&6; }
+if test $gcc_cv_header_valgrind_memcheck_h = yes; then
+
+$as_echo "#define HAVE_VALGRIND_MEMCHECK_H 1" >>confdefs.h
+
+fi
+if test $gcc_cv_header_memcheck_h = yes; then
+
+$as_echo "#define HAVE_MEMCHECK_H 1" >>confdefs.h
+
+fi
+
+if test x$ac_valgrind_checking != x ; then
# Prepare PATH_SEPARATOR.
# The user is always right.
@@ -6887,16 +6901,6 @@ fi
$as_echo "#define ENABLE_VALGRIND_CHECKING 1" >>confdefs.h
- if test $gcc_cv_header_valgrind_memcheck_h = yes; then
-
-$as_echo "#define HAVE_VALGRIND_MEMCHECK_H 1" >>confdefs.h
-
- fi
- if test $gcc_cv_header_memcheck_h = yes; then
-
-$as_echo "#define HAVE_MEMCHECK_H 1" >>confdefs.h
-
- fi
fi
@@ -6939,6 +6943,25 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
+# Check whether --enable-valgrind-annotations was given.
+if test "${enable_valgrind_annotations+set}" = set; then :
+ enableval=$enable_valgrind_annotations;
+else
+ enable_valgrind_annotations=no
+fi
+
+if test x$enable_valgrind_annotations != xno \
+ || test x$ac_valgrind_checking != x; then
+ if (test $have_valgrind_h = no \
+ && test $gcc_cv_header_memcheck_h = no \
+ && test $gcc_cv_header_valgrind_memcheck_h = no); then
+ as_fn_error "*** Can't find valgrind/memcheck.h, memcheck.h or valgrind.h" "$LINENO" 5
+ fi
+
+$as_echo "#define ENABLE_VALGRIND_ANNOTATIONS 1" >>confdefs.h
+
+fi
+
# -------------------------------
# Miscenalleous configure options
# -------------------------------
@@ -17971,7 +17994,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 17974 "configure"
+#line 17997 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -18077,7 +18100,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 18080 "configure"
+#line 18103 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -23306,13 +23329,8 @@ foo: .long 25
;;
i[34567]86-*-* | x86_64-*-*)
case "$target" in
- i[34567]86-*-solaris2.*)
- on_solaris=yes
- tga_func=___tls_get_addr
- ;;
- x86_64-*-solaris2.1[0-9]*)
+ i[34567]86-*-solaris2.* | x86_64-*-solaris2.1[0-9]*)
on_solaris=yes
- tga_func=__tls_get_addr
;;
*)
on_solaris=no
@@ -23587,7 +23605,6 @@ foo: .long 25
case "$target" in
sparc*-sun-solaris2.*)
on_solaris=yes
- tga_func=__tls_get_addr
;;
*)
on_solaris=no
@@ -23711,101 +23728,6 @@ if test $gcc_cv_as_tls = yes; then
set_have_as_tls=yes
fi
fi
-case "$target" in
- # TLS was introduced in the Solaris 9 FCS release. Support for GNU-style
- # TLS on x86 was only introduced in Solaris 9 4/04, replacing the earlier
- # Sun style that Sun ld and GCC don't support any longer.
- *-*-solaris2.*)
- ld_tls_support=yes
-
- save_LIBS="$LIBS"
- save_LDFLAGS="$LDFLAGS"
- LIBS=
- LDFLAGS=
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking library containing $tga_func" >&5
-$as_echo_n "checking library containing $tga_func... " >&6; }
- # Before Solaris 10, __tls_get_addr (SPARC/x64) resp. ___tls_get_addr
- # (32-bit x86) only lived in libthread, so check for that. Keep
- # set_have_as_tls if found, disable if not.
- as_ac_Search=`$as_echo "ac_cv_search_$tga_func" | $as_tr_sh`
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing $tga_func" >&5
-$as_echo_n "checking for library containing $tga_func... " >&6; }
-if { as_var=$as_ac_Search; eval "test \"\${$as_var+set}\" = set"; }; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $tga_func ();
-int
-main ()
-{
-return $tga_func ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' thread; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- eval "$as_ac_Search=\$ac_res"
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if { as_var=$as_ac_Search; eval "test \"\${$as_var+set}\" = set"; }; then :
- break
-fi
-done
-if { as_var=$as_ac_Search; eval "test \"\${$as_var+set}\" = set"; }; then :
-
-else
- eval "$as_ac_Search=no"
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-eval ac_res=\$$as_ac_Search
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-eval ac_res=\$$as_ac_Search
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-else
- set_have_as_tls=no
-fi
-
- ld_tls_libs="$LIBS"
- # Clear LIBS if we cannot support TLS.
- if test $set_have_as_tls = no; then
- LIBS=
- fi
- # Always define LIB_TLS_SPEC, even without TLS support.
-
-cat >>confdefs.h <<_ACEOF
-#define LIB_TLS_SPEC "$LIBS"
-_ACEOF
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBS" >&5
-$as_echo "$LIBS" >&6; }
-
- LIBS="$save_LIBS"
- LDFLAGS="$save_LDFLAGS"
- ;;
-esac
if test $set_have_as_tls = yes ; then
$as_echo "#define HAVE_AS_TLS 1" >>confdefs.h
@@ -24496,7 +24418,7 @@ else
.align 4
smac %g2, %g3, %g1
umac %g2, %g3, %g1
- cas [%g2], %g3, %g1' > conftest.s
+ casa [%g2] 0xb, %g3, %g1' > conftest.s
if { ac_try='$gcc_cv_as $gcc_cv_as_flags -Aleon -o conftest.o conftest.s >&5'
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
(eval $ac_try) 2>&5
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 1235501bd49..5565524c89a 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -514,27 +514,36 @@ dnl # an if statement. This was the source of very frustrating bugs
dnl # in converting to autoconf 2.5x!
AC_CHECK_HEADER(valgrind.h, have_valgrind_h=yes, have_valgrind_h=no)
-if test x$ac_valgrind_checking != x ; then
- # It is certainly possible that there's valgrind but no valgrind.h.
- # GCC relies on making annotations so we must have both.
- AC_MSG_CHECKING(for VALGRIND_DISCARD in <valgrind/memcheck.h>)
- AC_PREPROC_IFELSE([AC_LANG_SOURCE(
- [[#include <valgrind/memcheck.h>
+# It is certainly possible that there's valgrind but no valgrind.h.
+# GCC relies on making annotations so we must have both.
+AC_MSG_CHECKING(for VALGRIND_DISCARD in <valgrind/memcheck.h>)
+AC_PREPROC_IFELSE([AC_LANG_SOURCE(
+ [[#include <valgrind/memcheck.h>
#ifndef VALGRIND_DISCARD
#error VALGRIND_DISCARD not defined
#endif]])],
[gcc_cv_header_valgrind_memcheck_h=yes],
[gcc_cv_header_valgrind_memcheck_h=no])
- AC_MSG_RESULT($gcc_cv_header_valgrind_memcheck_h)
- AC_MSG_CHECKING(for VALGRIND_DISCARD in <memcheck.h>)
- AC_PREPROC_IFELSE([AC_LANG_SOURCE(
- [[#include <memcheck.h>
+AC_MSG_RESULT($gcc_cv_header_valgrind_memcheck_h)
+AC_MSG_CHECKING(for VALGRIND_DISCARD in <memcheck.h>)
+AC_PREPROC_IFELSE([AC_LANG_SOURCE(
+ [[#include <memcheck.h>
#ifndef VALGRIND_DISCARD
#error VALGRIND_DISCARD not defined
#endif]])],
[gcc_cv_header_memcheck_h=yes],
[gcc_cv_header_memcheck_h=no])
- AC_MSG_RESULT($gcc_cv_header_memcheck_h)
+AC_MSG_RESULT($gcc_cv_header_memcheck_h)
+if test $gcc_cv_header_valgrind_memcheck_h = yes; then
+ AC_DEFINE(HAVE_VALGRIND_MEMCHECK_H, 1,
+ [Define if valgrind's valgrind/memcheck.h header is installed.])
+fi
+if test $gcc_cv_header_memcheck_h = yes; then
+ AC_DEFINE(HAVE_MEMCHECK_H, 1,
+ [Define if valgrind's memcheck.h header is installed.])
+fi
+
+if test x$ac_valgrind_checking != x ; then
AM_PATH_PROG_WITH_TEST(valgrind_path, valgrind,
[$ac_dir/$ac_word --version | grep valgrind- >/dev/null 2>&1])
if test "x$valgrind_path" = "x" \
@@ -548,14 +557,6 @@ if test x$ac_valgrind_checking != x ; then
AC_DEFINE(ENABLE_VALGRIND_CHECKING, 1,
[Define if you want to run subprograms and generated programs
through valgrind (a memory checker). This is extremely expensive.])
- if test $gcc_cv_header_valgrind_memcheck_h = yes; then
- AC_DEFINE(HAVE_VALGRIND_MEMCHECK_H, 1,
- [Define if valgrind's valgrind/memcheck.h header is installed.])
- fi
- if test $gcc_cv_header_memcheck_h = yes; then
- AC_DEFINE(HAVE_MEMCHECK_H, 1,
- [Define if valgrind's memcheck.h header is installed.])
- fi
fi
AC_SUBST(valgrind_path_defines)
AC_SUBST(valgrind_command)
@@ -594,6 +595,21 @@ gather_stats=`if test $enable_gather_detailed_mem_stats != no; then echo 1; else
AC_DEFINE_UNQUOTED(GATHER_STATISTICS, $gather_stats,
[Define to enable detailed memory allocation stats gathering.])
+AC_ARG_ENABLE(valgrind-annotations,
+[AS_HELP_STRING([--enable-valgrind-annotations],
+ [enable valgrind runtime interaction])], [],
+[enable_valgrind_annotations=no])
+if test x$enable_valgrind_annotations != xno \
+ || test x$ac_valgrind_checking != x; then
+ if (test $have_valgrind_h = no \
+ && test $gcc_cv_header_memcheck_h = no \
+ && test $gcc_cv_header_valgrind_memcheck_h = no); then
+ AC_MSG_ERROR([*** Can't find valgrind/memcheck.h, memcheck.h or valgrind.h])
+ fi
+ AC_DEFINE(ENABLE_VALGRIND_ANNOTATIONS, 1,
+[Define to get calls to the valgrind runtime enabled.])
+fi
+
# -------------------------------
# Miscenalleous configure options
# -------------------------------
@@ -2935,13 +2951,8 @@ foo: .long 25
;;
i[34567]86-*-* | x86_64-*-*)
case "$target" in
- i[34567]86-*-solaris2.*)
- on_solaris=yes
- tga_func=___tls_get_addr
- ;;
- x86_64-*-solaris2.1[0-9]*)
+ i[34567]86-*-solaris2.* | x86_64-*-solaris2.1[0-9]*)
on_solaris=yes
- tga_func=__tls_get_addr
;;
*)
on_solaris=no
@@ -3217,7 +3228,6 @@ foo: .long 25
case "$target" in
sparc*-sun-solaris2.*)
on_solaris=yes
- tga_func=__tls_get_addr
;;
*)
on_solaris=no
@@ -3313,37 +3323,6 @@ else
[$tls_first_major,$tls_first_minor,0], [$tls_as_opt], [$conftest_s],,
[set_have_as_tls=yes])
fi
-case "$target" in
- # TLS was introduced in the Solaris 9 FCS release. Support for GNU-style
- # TLS on x86 was only introduced in Solaris 9 4/04, replacing the earlier
- # Sun style that Sun ld and GCC don't support any longer.
- *-*-solaris2.*)
- ld_tls_support=yes
-
- save_LIBS="$LIBS"
- save_LDFLAGS="$LDFLAGS"
- LIBS=
- LDFLAGS=
-
- AC_MSG_CHECKING(library containing $tga_func)
- # Before Solaris 10, __tls_get_addr (SPARC/x64) resp. ___tls_get_addr
- # (32-bit x86) only lived in libthread, so check for that. Keep
- # set_have_as_tls if found, disable if not.
- AC_SEARCH_LIBS([$tga_func], [thread],, [set_have_as_tls=no])
- ld_tls_libs="$LIBS"
- # Clear LIBS if we cannot support TLS.
- if test $set_have_as_tls = no; then
- LIBS=
- fi
- # Always define LIB_TLS_SPEC, even without TLS support.
- AC_DEFINE_UNQUOTED(LIB_TLS_SPEC, "$LIBS",
- [Define to the library containing __tls_get_addr/___tls_get_addr.])
- AC_MSG_RESULT($LIBS)
-
- LIBS="$save_LIBS"
- LDFLAGS="$save_LDFLAGS"
- ;;
-esac
if test $set_have_as_tls = yes ; then
AC_DEFINE(HAVE_AS_TLS, 1,
[Define if your assembler and linker support thread-local storage.])
@@ -3684,7 +3663,7 @@ foo:
.align 4
smac %g2, %g3, %g1
umac %g2, %g3, %g1
- cas [[%g2]], %g3, %g1],,
+ casa [[%g2]] 0xb, %g3, %g1],,
[AC_DEFINE(HAVE_AS_LEON, 1,
[Define if your assembler supports LEON instructions.])])
;;
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index ae213426553..a5f3829d705 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,15 @@
+2014-04-28 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/59120
+ * parser.c (cp_parser_alias_declaration): Check return value of
+ cp_parser_require.
+
+2014-04-24 Jakub Jelinek <jakub@redhat.com>
+
+ * parser.c (cp_parser_omp_atomic): Allow seq_cst before
+ atomic-clause, allow comma in between atomic-clause and
+ seq_cst.
+
2014-04-24 Marc Glisse <marc.glisse@inria.fr>
PR libstdc++/43622
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 4e6a2b88f32..962cacedf80 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -16142,15 +16142,8 @@ cp_parser_alias_declaration (cp_parser* parser)
if (parser->num_template_parameter_lists)
parser->type_definition_forbidden_message = saved_message;
- if (type == error_mark_node)
- {
- cp_parser_skip_to_end_of_block_or_statement (parser);
- return error_mark_node;
- }
-
- cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
-
- if (cp_parser_error_occurred (parser))
+ if (type == error_mark_node
+ || !cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON))
{
cp_parser_skip_to_end_of_block_or_statement (parser);
return error_mark_node;
@@ -28534,6 +28527,20 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok)
tree id = cp_lexer_peek_token (parser->lexer)->u.value;
const char *p = IDENTIFIER_POINTER (id);
+ if (!strcmp (p, "seq_cst"))
+ {
+ seq_cst = true;
+ cp_lexer_consume_token (parser->lexer);
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)
+ && cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_NAME)
+ cp_lexer_consume_token (parser->lexer);
+ }
+ }
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p = IDENTIFIER_POINTER (id);
+
if (!strcmp (p, "read"))
code = OMP_ATOMIC_READ;
else if (!strcmp (p, "write"))
@@ -28547,16 +28554,22 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok)
if (p)
cp_lexer_consume_token (parser->lexer);
}
-
- if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ if (!seq_cst)
{
- tree id = cp_lexer_peek_token (parser->lexer)->u.value;
- const char *p = IDENTIFIER_POINTER (id);
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)
+ && cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_NAME)
+ cp_lexer_consume_token (parser->lexer);
- if (!strcmp (p, "seq_cst"))
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
{
- seq_cst = true;
- cp_lexer_consume_token (parser->lexer);
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p = IDENTIFIER_POINTER (id);
+
+ if (!strcmp (p, "seq_cst"))
+ {
+ seq_cst = true;
+ cp_lexer_consume_token (parser->lexer);
+ }
}
}
cp_parser_require_pragma_eol (parser, pragma_tok);
diff --git a/gcc/cselib.c b/gcc/cselib.c
index c55b02772ed..00a04baab6e 100644
--- a/gcc/cselib.c
+++ b/gcc/cselib.c
@@ -49,9 +49,6 @@ struct elt_list {
cselib_val *elt;
};
-/* See the documentation of cselib_find_slot below. */
-static enum machine_mode find_slot_memmode;
-
static bool cselib_record_memory;
static bool cselib_preserve_constants;
static bool cselib_any_perm_equivs;
@@ -94,7 +91,14 @@ static rtx cselib_expand_value_rtx_1 (rtx, struct expand_value_data *, int);
struct cselib_hasher : typed_noop_remove <cselib_val>
{
typedef cselib_val value_type;
- typedef rtx_def compare_type;
+ struct compare_type {
+ /* The rtx value and its mode (needed separately for constant
+ integers). */
+ enum machine_mode mode;
+ rtx x;
+ /* The mode of the contaning MEM, if any, otherwise VOIDmode. */
+ enum machine_mode memmode;
+ };
static inline hashval_t hash (const value_type *);
static inline bool equal (const value_type *, const compare_type *);
};
@@ -118,27 +122,20 @@ inline bool
cselib_hasher::equal (const value_type *v, const compare_type *x_arg)
{
struct elt_loc_list *l;
- rtx x = CONST_CAST_RTX (x_arg);
- enum machine_mode mode = GET_MODE (x);
-
- gcc_assert (!CONST_SCALAR_INT_P (x) && GET_CODE (x) != CONST_FIXED);
+ rtx x = x_arg->x;
+ enum machine_mode mode = x_arg->mode;
+ enum machine_mode memmode = x_arg->memmode;
if (mode != GET_MODE (v->val_rtx))
return false;
- /* Unwrap X if necessary. */
- if (GET_CODE (x) == CONST
- && (CONST_SCALAR_INT_P (XEXP (x, 0))
- || GET_CODE (XEXP (x, 0)) == CONST_FIXED))
- x = XEXP (x, 0);
-
if (GET_CODE (x) == VALUE)
return x == v->val_rtx;
/* We don't guarantee that distinct rtx's have different hash values,
so we need to do a comparison. */
for (l = v->locs; l; l = l->next)
- if (rtx_equal_for_cselib_1 (l->loc, x, find_slot_memmode))
+ if (rtx_equal_for_cselib_1 (l->loc, x, memmode))
{
promote_debug_loc (l);
return true;
@@ -498,8 +495,11 @@ preserve_constants_and_equivs (cselib_val **x, void *info ATTRIBUTE_UNUSED)
if (invariant_or_equiv_p (v))
{
+ cselib_hasher::compare_type lookup = {
+ GET_MODE (v->val_rtx), v->val_rtx, VOIDmode
+ };
cselib_val **slot
- = cselib_preserved_hash_table.find_slot_with_hash (v->val_rtx,
+ = cselib_preserved_hash_table.find_slot_with_hash (&lookup,
v->hash, INSERT);
gcc_assert (!*slot);
*slot = v;
@@ -572,22 +572,19 @@ cselib_get_next_uid (void)
/* Search for X, whose hashcode is HASH, in CSELIB_HASH_TABLE,
INSERTing if requested. When X is part of the address of a MEM,
- MEMMODE should specify the mode of the MEM. While searching the
- table, MEMMODE is held in FIND_SLOT_MEMMODE, so that autoinc RTXs
- in X can be resolved. */
+ MEMMODE should specify the mode of the MEM. */
static cselib_val **
-cselib_find_slot (rtx x, hashval_t hash, enum insert_option insert,
- enum machine_mode memmode)
+cselib_find_slot (enum machine_mode mode, rtx x, hashval_t hash,
+ enum insert_option insert, enum machine_mode memmode)
{
cselib_val **slot = NULL;
- find_slot_memmode = memmode;
+ cselib_hasher::compare_type lookup = { mode, x, memmode };
if (cselib_preserve_constants)
- slot = cselib_preserved_hash_table.find_slot_with_hash (x, hash,
+ slot = cselib_preserved_hash_table.find_slot_with_hash (&lookup, hash,
NO_INSERT);
if (!slot)
- slot = cselib_hash_table.find_slot_with_hash (x, hash, insert);
- find_slot_memmode = VOIDmode;
+ slot = cselib_hash_table.find_slot_with_hash (&lookup, hash, insert);
return slot;
}
@@ -1041,18 +1038,6 @@ rtx_equal_for_cselib_1 (rtx x, rtx y, enum machine_mode memmode)
return 1;
}
-/* We need to pass down the mode of constants through the hash table
- functions. For that purpose, wrap them in a CONST of the appropriate
- mode. */
-static rtx
-wrap_constant (enum machine_mode mode, rtx x)
-{
- if (!CONST_SCALAR_INT_P (x) && GET_CODE (x) != CONST_FIXED)
- return x;
- gcc_assert (mode != VOIDmode);
- return gen_rtx_CONST (mode, x);
-}
-
/* Hash an rtx. Return 0 if we couldn't hash the rtx.
For registers and memory locations, we look up their cselib_val structure
and return its VALUE element.
@@ -1411,8 +1396,7 @@ cselib_lookup_mem (rtx x, int create)
mem_elt = new_cselib_val (next_uid, mode, x);
add_mem_for_addr (addr, mem_elt, x);
- slot = cselib_find_slot (wrap_constant (mode, x), mem_elt->hash,
- INSERT, mode);
+ slot = cselib_find_slot (mode, x, mem_elt->hash, INSERT, VOIDmode);
*slot = mem_elt;
return mem_elt;
}
@@ -2068,7 +2052,7 @@ cselib_lookup_1 (rtx x, enum machine_mode mode,
}
}
REG_VALUES (i)->next = new_elt_list (REG_VALUES (i)->next, e);
- slot = cselib_find_slot (x, e->hash, INSERT, memmode);
+ slot = cselib_find_slot (mode, x, e->hash, INSERT, memmode);
*slot = e;
return e;
}
@@ -2081,7 +2065,7 @@ cselib_lookup_1 (rtx x, enum machine_mode mode,
if (! hashval)
return 0;
- slot = cselib_find_slot (wrap_constant (mode, x), hashval,
+ slot = cselib_find_slot (mode, x, hashval,
create ? INSERT : NO_INSERT, memmode);
if (slot == 0)
return 0;
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 347a94a3aee..9780d923804 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -12787,9 +12787,12 @@ float __builtin_recipdivf (float, float);
float __builtin_rsqrtf (float);
double __builtin_recipdiv (double, double);
double __builtin_rsqrt (double);
-long __builtin_bpermd (long, long);
uint64_t __builtin_ppc_get_timebase ();
unsigned long __builtin_ppc_mftb ();
+double __builtin_unpack_longdouble (long double, int);
+double __builtin_longdouble_dw0 (long double);
+double __builtin_longdouble_dw1 (long double);
+long double __builtin_pack_longdouble (double, double);
@end smallexample
The @code{vec_rsqrt}, @code{__builtin_rsqrt}, and
@@ -12809,6 +12812,57 @@ The @code{__builtin_ppc_mftb} function always generates one instruction and
returns the Time Base Register value as an unsigned long, throwing away
the most significant word on 32-bit environments.
+The following built-in functions are available for the PowerPC family
+of processors, starting with ISA 2.06 or later (@option{-mcpu=power7}
+or @option{-mpopcntd}):
+@smallexample
+long __builtin_bpermd (long, long);
+int __builtin_divwe (int, int);
+int __builtin_divweo (int, int);
+unsigned int __builtin_divweu (unsigned int, unsigned int);
+unsigned int __builtin_divweuo (unsigned int, unsigned int);
+long __builtin_divde (long, long);
+long __builtin_divdeo (long, long);
+unsigned long __builtin_divdeu (unsigned long, unsigned long);
+unsigned long __builtin_divdeuo (unsigned long, unsigned long);
+unsigned int cdtbcd (unsigned int);
+unsigned int cbcdtd (unsigned int);
+unsigned int addg6s (unsigned int, unsigned int);
+@end smallexample
+
+The @code{__builtin_divde}, @code{__builtin_divdeo},
+@code{__builitin_divdeu}, @code{__builtin_divdeou} functions require a
+64-bit environment support ISA 2.06 or later.
+
+The following built-in functions are available for the PowerPC family
+of processors when hardware decimal floating point
+(@option{-mhard-dfp}) is available:
+@smallexample
+_Decimal64 __builtin_dxex (_Decimal64);
+_Decimal128 __builtin_dxexq (_Decimal128);
+_Decimal64 __builtin_ddedpd (int, _Decimal64);
+_Decimal128 __builtin_ddedpdq (int, _Decimal128);
+_Decimal64 __builtin_denbcd (int, _Decimal64);
+_Decimal128 __builtin_denbcdq (int, _Decimal128);
+_Decimal64 __builtin_diex (_Decimal64, _Decimal64);
+_Decimal128 _builtin_diexq (_Decimal128, _Decimal128);
+_Decimal64 __builtin_dscli (_Decimal64, int);
+_Decimal128 __builitn_dscliq (_Decimal128, int);
+_Decimal64 __builtin_dscri (_Decimal64, int);
+_Decimal128 __builitn_dscriq (_Decimal128, int);
+unsigned long long __builtin_unpack_dec128 (_Decimal128, int);
+_Decimal128 __builtin_pack_dec128 (unsigned long long, unsigned long long);
+@end smallexample
+
+The following built-in functions are available for the PowerPC family
+of processors when the Vector Scalar (vsx) instruction set is
+available:
+@smallexample
+unsigned long long __builtin_unpack_vector_int128 (vector __int128_t, int);
+vector __int128_t __builtin_pack_vector_int128 (unsigned long long,
+ unsigned long long);
+@end smallexample
+
@node PowerPC AltiVec/VSX Built-in Functions
@subsection PowerPC AltiVec Built-in Functions
@@ -15220,6 +15274,17 @@ vector __uint128_t vec_vsubcuq (vector __uint128_t, vector __uint128_t);
__int128_t vec_vsubuqm (__int128_t, __int128_t);
__uint128_t vec_vsubuqm (__uint128_t, __uint128_t);
+
+vector __int128_t __builtin_bcdadd (vector __int128_t, vector__int128_t);
+int __builtin_bcdadd_lt (vector __int128_t, vector__int128_t);
+int __builtin_bcdadd_eq (vector __int128_t, vector__int128_t);
+int __builtin_bcdadd_gt (vector __int128_t, vector__int128_t);
+int __builtin_bcdadd_ov (vector __int128_t, vector__int128_t);
+vector __int128_t bcdsub (vector __int128_t, vector__int128_t);
+int __builtin_bcdsub_lt (vector __int128_t, vector__int128_t);
+int __builtin_bcdsub_eq (vector __int128_t, vector__int128_t);
+int __builtin_bcdsub_gt (vector __int128_t, vector__int128_t);
+int __builtin_bcdsub_ov (vector __int128_t, vector__int128_t);
@end smallexample
If the cryptographic instructions are enabled (@option{-mcrypto} or
diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index 0b2b3657577..7851b0061b3 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -2544,8 +2544,7 @@ Finally a @code{stagefeedback} compiler is built using the information collected
Unlike standard bootstrap, several additional restrictions apply. The
compiler used to build @code{stage1} needs to support a 64-bit integral type.
-It is recommended to only use GCC for this. Also parallel make is currently
-not supported since collisions in profile collecting may occur.
+It is recommended to only use GCC for this.
@html
<hr />
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index ff43f262323..da7a00ed00c 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -993,6 +993,7 @@ See RS/6000 and PowerPC Options.
-mhard-quad-float -msoft-quad-float @gol
-mstack-bias -mno-stack-bias @gol
-munaligned-doubles -mno-unaligned-doubles @gol
+-muser-mode -mno-user-mode @gol
-mv8plus -mno-v8plus -mvis -mno-vis @gol
-mvis2 -mno-vis2 -mvis3 -mno-vis3 @gol
-mcbcond -mno-cbcond @gol
@@ -20961,6 +20962,14 @@ Specifying this option avoids some rare compatibility problems with code
generated by other compilers. It is not the default because it results
in a performance loss, especially for floating-point code.
+@item -muser-mode
+@itemx -mno-user-mode
+@opindex muser-mode
+@opindex mno-user-mode
+Do not generate code that can only run in supervisor mode. This is relevant
+only for the @code{casa} instruction emitted for the LEON3 processor. The
+default is @option{-mno-user-mode}.
+
@item -mno-faster-structs
@itemx -mfaster-structs
@opindex mno-faster-structs
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 2b2ab5dd831..da0b3f589c9 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -6917,14 +6917,13 @@ should_move_die_to_comdat (dw_die_ref die)
case DW_TAG_structure_type:
case DW_TAG_enumeration_type:
case DW_TAG_union_type:
- /* Don't move declarations, inlined instances, or types nested in a
- subprogram. */
+ /* Don't move declarations, inlined instances, types nested in a
+ subprogram, or types that contain subprogram definitions. */
if (is_declaration_die (die)
|| get_AT (die, DW_AT_abstract_origin)
- || is_nested_in_subprogram (die))
+ || is_nested_in_subprogram (die)
+ || contains_subprogram_definition (die))
return 0;
- /* A type definition should never contain a subprogram definition. */
- gcc_assert (!contains_subprogram_definition (die));
return 1;
case DW_TAG_array_type:
case DW_TAG_interface_type:
@@ -7013,6 +7012,7 @@ clone_as_declaration (dw_die_ref die)
switch (a->dw_attr)
{
+ case DW_AT_abstract_origin:
case DW_AT_artificial:
case DW_AT_containing_type:
case DW_AT_external:
@@ -7245,6 +7245,12 @@ generate_skeleton_bottom_up (skeleton_chain_node *parent)
dw_die_ref clone = clone_die (c);
move_all_children (c, clone);
+ /* If the original has a DW_AT_object_pointer attribute,
+ it would now point to a child DIE just moved to the
+ cloned tree, so we need to remove that attribute from
+ the original. */
+ remove_AT (c, DW_AT_object_pointer);
+
replace_child (c, clone, prev);
generate_skeleton_ancestor_tree (parent);
add_child_die (parent->new_die, c);
@@ -7386,28 +7392,38 @@ break_out_comdat_types (dw_die_ref die)
} while (next != NULL);
}
-/* Like clone_tree, but additionally enter all the children into
- the hash table decl_table. */
+/* Like clone_tree, but copy DW_TAG_subprogram DIEs as declarations.
+ Enter all the cloned children into the hash table decl_table. */
static dw_die_ref
-clone_tree_hash (dw_die_ref die, decl_hash_type decl_table)
+clone_tree_partial (dw_die_ref die, decl_hash_type decl_table)
{
dw_die_ref c;
- dw_die_ref clone = clone_die (die);
+ dw_die_ref clone;
struct decl_table_entry *entry;
- decl_table_entry **slot = decl_table.find_slot_with_hash (die,
- htab_hash_pointer (die), INSERT);
+ decl_table_entry **slot;
+
+ if (die->die_tag == DW_TAG_subprogram)
+ clone = clone_as_declaration (die);
+ else
+ clone = clone_die (die);
+
+ slot = decl_table.find_slot_with_hash (die,
+ htab_hash_pointer (die), INSERT);
+
/* Assert that DIE isn't in the hash table yet. If it would be there
before, the ancestors would be necessarily there as well, therefore
- clone_tree_hash wouldn't be called. */
+ clone_tree_partial wouldn't be called. */
gcc_assert (*slot == HTAB_EMPTY_ENTRY);
+
entry = XCNEW (struct decl_table_entry);
entry->orig = die;
entry->copy = clone;
*slot = entry;
- FOR_EACH_CHILD (die, c,
- add_child_die (clone, clone_tree_hash (c, decl_table)));
+ if (die->die_tag != DW_TAG_subprogram)
+ FOR_EACH_CHILD (die, c,
+ add_child_die (clone, clone_tree_partial (c, decl_table)));
return clone;
}
@@ -7458,9 +7474,15 @@ copy_decls_walk (dw_die_ref unit, dw_die_ref die, decl_hash_type decl_table)
entry->copy = copy;
*slot = entry;
- FOR_EACH_CHILD (targ, c,
- add_child_die (copy,
- clone_tree_hash (c, decl_table)));
+ /* If TARG is not a declaration DIE, we need to copy its
+ children. */
+ if (!is_declaration_die (targ))
+ {
+ FOR_EACH_CHILD (
+ targ, c,
+ add_child_die (copy,
+ clone_tree_partial (c, decl_table)));
+ }
/* Make sure the cloned tree is marked as part of the
type unit. */
diff --git a/gcc/expr.c b/gcc/expr.c
index fe95ebcbfa0..989a8780dc9 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -2365,6 +2365,18 @@ use_reg_mode (rtx *call_fusage, rtx reg, enum machine_mode mode)
= gen_rtx_EXPR_LIST (mode, gen_rtx_USE (VOIDmode, reg), *call_fusage);
}
+/* Add a CLOBBER expression for REG to the (possibly empty) list pointed
+ to by CALL_FUSAGE. REG must denote a hard register. */
+
+void
+clobber_reg_mode (rtx *call_fusage, rtx reg, enum machine_mode mode)
+{
+ gcc_assert (REG_P (reg) && REGNO (reg) < FIRST_PSEUDO_REGISTER);
+
+ *call_fusage
+ = gen_rtx_EXPR_LIST (mode, gen_rtx_CLOBBER (VOIDmode, reg), *call_fusage);
+}
+
/* Add USE expressions to *CALL_FUSAGE for each of NREGS consecutive regs,
starting at REGNO. All of these registers must be hard registers. */
diff --git a/gcc/expr.h b/gcc/expr.h
index 524da6731a9..1823febac26 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -346,6 +346,7 @@ extern void copy_blkmode_from_reg (rtx, rtx, tree);
/* Mark REG as holding a parameter for the next CALL_INSN.
Mode is TYPE_MODE of the non-promoted parameter, or VOIDmode. */
extern void use_reg_mode (rtx *, rtx, enum machine_mode);
+extern void clobber_reg_mode (rtx *, rtx, enum machine_mode);
extern rtx copy_blkmode_to_reg (enum machine_mode, tree);
@@ -356,6 +357,13 @@ use_reg (rtx *fusage, rtx reg)
use_reg_mode (fusage, reg, VOIDmode);
}
+/* Mark REG as clobbered by the call with FUSAGE as CALL_INSN_FUNCTION_USAGE. */
+static inline void
+clobber_reg (rtx *fusage, rtx reg)
+{
+ clobber_reg_mode (fusage, reg, VOIDmode);
+}
+
/* Mark NREGS consecutive regs, starting at REGNO, as holding parameters
for the next CALL_INSN. */
extern void use_regs (rtx *, int, int);
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 427c9b15ad8..5cf25134e30 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,23 @@
+2014-03-27 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/59604
+ PR fortran/58003
+ * gfortran.h (gfc_convert_mpz_to_signed): Add prototype.
+ * arith.c (gfc_int2int): Convert number to signed if
+ arithmetic overflow is not checked.
+ * simplify.c (convert_mpz_to_unsigned): Only trigger assert for
+ size if range checking is in force.
+ (convert_mpz_to_signed): Make non-static, rename to
+ (gfc_convert_mpz_to_signed).
+ (simplify_dshift): Use gfc_convert_mpz_to_signed.
+ (gfc_simplify_ibclr): Likewise.
+ (gfc_simplify_ibits): Likewise.
+ (gfc_simplify_ibset): Likewise.
+ (simplify_shift): Likewise.
+ (gfc_simplify_ishiftc): Likewise.
+ (gfc_simplify_maskr): Likewise.
+ (gfc_simplify_maskl): Likewise.
+
2014-04-22 Tobias Burnus <burnus@net-b.de>
PR fortran/60881
diff --git a/gcc/fortran/arith.c b/gcc/fortran/arith.c
index 053cf765e59..a05fa4907a4 100644
--- a/gcc/fortran/arith.c
+++ b/gcc/fortran/arith.c
@@ -1976,6 +1976,17 @@ gfc_int2int (gfc_expr *src, int kind)
}
}
+ /* If we do not trap numeric overflow, we need to convert the number to
+ signed, throwing away high-order bits if necessary. */
+ if (gfc_option.flag_range_check == 0)
+ {
+ int k;
+
+ k = gfc_validate_kind (BT_INTEGER, kind, false);
+ gfc_convert_mpz_to_signed (result->value.integer,
+ gfc_integer_kinds[k].bit_size);
+ }
+
return result;
}
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 14c202dd413..f0eed809ab8 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -3022,4 +3022,8 @@ typedef int (*walk_expr_fn_t) (gfc_expr **, int *, void *);
int gfc_expr_walker (gfc_expr **, walk_expr_fn_t, void *);
int gfc_code_walker (gfc_code **, walk_code_fn_t, walk_expr_fn_t, void *);
+/* simplify.c */
+
+void gfc_convert_mpz_to_signed (mpz_t, int);
+
#endif /* GCC_GFORTRAN_H */
diff --git a/gcc/fortran/simplify.c b/gcc/fortran/simplify.c
index 96d0f21f36c..1b6cd5bc4c1 100644
--- a/gcc/fortran/simplify.c
+++ b/gcc/fortran/simplify.c
@@ -151,8 +151,10 @@ convert_mpz_to_unsigned (mpz_t x, int bitsize)
if (mpz_sgn (x) < 0)
{
- /* Confirm that no bits above the signed range are unset. */
- gcc_assert (mpz_scan0 (x, bitsize-1) == ULONG_MAX);
+ /* Confirm that no bits above the signed range are unset if we
+ are doing range checking. */
+ if (gfc_option.flag_range_check != 0)
+ gcc_assert (mpz_scan0 (x, bitsize-1) == ULONG_MAX);
mpz_init_set_ui (mask, 1);
mpz_mul_2exp (mask, mask, bitsize);
@@ -175,13 +177,15 @@ convert_mpz_to_unsigned (mpz_t x, int bitsize)
If the bitsize-1 bit is set, this is taken as a sign bit and
the number is converted to the corresponding negative number. */
-static void
-convert_mpz_to_signed (mpz_t x, int bitsize)
+void
+gfc_convert_mpz_to_signed (mpz_t x, int bitsize)
{
mpz_t mask;
- /* Confirm that no bits above the unsigned range are set. */
- gcc_assert (mpz_scan1 (x, bitsize) == ULONG_MAX);
+ /* Confirm that no bits above the unsigned range are set if we are
+ doing range checking. */
+ if (gfc_option.flag_range_check != 0)
+ gcc_assert (mpz_scan1 (x, bitsize) == ULONG_MAX);
if (mpz_tstbit (x, bitsize - 1) == 1)
{
@@ -1943,7 +1947,7 @@ simplify_dshift (gfc_expr *arg1, gfc_expr *arg2, gfc_expr *shiftarg,
mpz_setbit (result->value.integer, shift + i);
/* Convert to a signed value. */
- convert_mpz_to_signed (result->value.integer, size);
+ gfc_convert_mpz_to_signed (result->value.integer, size);
return result;
}
@@ -2561,7 +2565,7 @@ gfc_simplify_ibclr (gfc_expr *x, gfc_expr *y)
mpz_clrbit (result->value.integer, pos);
- convert_mpz_to_signed (result->value.integer,
+ gfc_convert_mpz_to_signed (result->value.integer,
gfc_integer_kinds[k].bit_size);
return result;
@@ -2619,7 +2623,7 @@ gfc_simplify_ibits (gfc_expr *x, gfc_expr *y, gfc_expr *z)
free (bits);
- convert_mpz_to_signed (result->value.integer,
+ gfc_convert_mpz_to_signed (result->value.integer,
gfc_integer_kinds[k].bit_size);
return result;
@@ -2646,7 +2650,7 @@ gfc_simplify_ibset (gfc_expr *x, gfc_expr *y)
mpz_setbit (result->value.integer, pos);
- convert_mpz_to_signed (result->value.integer,
+ gfc_convert_mpz_to_signed (result->value.integer,
gfc_integer_kinds[k].bit_size);
return result;
@@ -3093,7 +3097,7 @@ simplify_shift (gfc_expr *e, gfc_expr *s, const char *name,
}
}
- convert_mpz_to_signed (result->value.integer, bitsize);
+ gfc_convert_mpz_to_signed (result->value.integer, bitsize);
free (bits);
return result;
@@ -3234,7 +3238,7 @@ gfc_simplify_ishftc (gfc_expr *e, gfc_expr *s, gfc_expr *sz)
}
}
- convert_mpz_to_signed (result->value.integer, isize);
+ gfc_convert_mpz_to_signed (result->value.integer, isize);
free (bits);
return result;
@@ -3954,7 +3958,7 @@ gfc_simplify_maskr (gfc_expr *i, gfc_expr *kind_arg)
mpz_mul_2exp (result->value.integer, result->value.integer, arg);
mpz_sub_ui (result->value.integer, result->value.integer, 1);
- convert_mpz_to_signed (result->value.integer, gfc_integer_kinds[k].bit_size);
+ gfc_convert_mpz_to_signed (result->value.integer, gfc_integer_kinds[k].bit_size);
return result;
}
@@ -3990,7 +3994,7 @@ gfc_simplify_maskl (gfc_expr *i, gfc_expr *kind_arg)
mpz_sub (result->value.integer, z, result->value.integer);
mpz_clear (z);
- convert_mpz_to_signed (result->value.integer, gfc_integer_kinds[k].bit_size);
+ gfc_convert_mpz_to_signed (result->value.integer, gfc_integer_kinds[k].bit_size);
return result;
}
diff --git a/gcc/gimple-ssa-strength-reduction.c b/gcc/gimple-ssa-strength-reduction.c
index cf252d4269d..af9f26d2e9c 100644
--- a/gcc/gimple-ssa-strength-reduction.c
+++ b/gcc/gimple-ssa-strength-reduction.c
@@ -1111,14 +1111,17 @@ create_mul_imm_cand (gimple gs, tree base_in, tree stride_in, bool speed)
X = Y * c
============================
X = (B + i') * (S * c) */
- base = base_cand->base_expr;
- index = base_cand->index;
temp = wi::to_widest (base_cand->stride) * wi::to_widest (stride_in);
- stride = wide_int_to_tree (TREE_TYPE (stride_in), temp);
- ctype = base_cand->cand_type;
- if (has_single_use (base_in))
- savings = (base_cand->dead_savings
- + stmt_cost (base_cand->cand_stmt, speed));
+ if (wi::fits_to_tree_p (temp, TREE_TYPE (stride_in)))
+ {
+ base = base_cand->base_expr;
+ index = base_cand->index;
+ stride = wide_int_to_tree (TREE_TYPE (stride_in), temp);
+ ctype = base_cand->cand_type;
+ if (has_single_use (base_in))
+ savings = (base_cand->dead_savings
+ + stmt_cost (base_cand->cand_stmt, speed));
+ }
}
else if (base_cand->kind == CAND_ADD && integer_onep (base_cand->stride))
{
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index d7470fbb0a6..008a2528644 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -5796,7 +5796,7 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code)
to the contrary in the innermost scope, generate an error. */
static bool
-omp_is_private (struct gimplify_omp_ctx *ctx, tree decl, bool simd)
+omp_is_private (struct gimplify_omp_ctx *ctx, tree decl, int simd)
{
splay_tree_node n;
@@ -5830,13 +5830,13 @@ omp_is_private (struct gimplify_omp_ctx *ctx, tree decl, bool simd)
else if ((n->value & GOVD_REDUCTION) != 0)
error ("iteration variable %qE should not be reduction",
DECL_NAME (decl));
- else if (simd && (n->value & GOVD_LASTPRIVATE) != 0)
+ else if (simd == 1 && (n->value & GOVD_LASTPRIVATE) != 0)
error ("iteration variable %qE should not be lastprivate",
DECL_NAME (decl));
else if (simd && (n->value & GOVD_PRIVATE) != 0)
error ("iteration variable %qE should not be private",
DECL_NAME (decl));
- else if (simd && (n->value & GOVD_LINEAR) != 0)
+ else if (simd == 2 && (n->value & GOVD_LINEAR) != 0)
error ("iteration variable %qE is predetermined linear",
DECL_NAME (decl));
}
@@ -6602,8 +6602,8 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
orig_for_stmt = for_stmt = *expr_p;
- simd = TREE_CODE (for_stmt) == OMP_SIMD
- || TREE_CODE (for_stmt) == CILK_SIMD;
+ simd = (TREE_CODE (for_stmt) == OMP_SIMD
+ || TREE_CODE (for_stmt) == CILK_SIMD);
gimplify_scan_omp_clauses (&OMP_FOR_CLAUSES (for_stmt), pre_p,
simd ? ORT_SIMD : ORT_WORKSHARE);
@@ -6659,13 +6659,16 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
/* Make sure the iteration variable is private. */
tree c = NULL_TREE;
+ tree c2 = NULL_TREE;
if (orig_for_stmt != for_stmt)
/* Do this only on innermost construct for combined ones. */;
else if (simd)
{
splay_tree_node n = splay_tree_lookup (gimplify_omp_ctxp->variables,
(splay_tree_key)decl);
- omp_is_private (gimplify_omp_ctxp, decl, simd);
+ omp_is_private (gimplify_omp_ctxp, decl,
+ 1 + (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt))
+ != 1));
if (n != NULL && (n->value & GOVD_DATA_SHARE_CLASS) != 0)
omp_notice_variable (gimplify_omp_ctxp, decl, true);
else if (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) == 1)
@@ -6691,13 +6694,14 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
: OMP_CLAUSE_PRIVATE);
OMP_CLAUSE_DECL (c) = decl;
OMP_CLAUSE_CHAIN (c) = OMP_FOR_CLAUSES (for_stmt);
+ OMP_FOR_CLAUSES (for_stmt) = c;
omp_add_variable (gimplify_omp_ctxp, decl,
(lastprivate ? GOVD_LASTPRIVATE : GOVD_PRIVATE)
- | GOVD_SEEN);
+ | GOVD_EXPLICIT | GOVD_SEEN);
c = NULL_TREE;
}
}
- else if (omp_is_private (gimplify_omp_ctxp, decl, simd))
+ else if (omp_is_private (gimplify_omp_ctxp, decl, 0))
omp_notice_variable (gimplify_omp_ctxp, decl, true);
else
omp_add_variable (gimplify_omp_ctxp, decl, GOVD_PRIVATE | GOVD_SEEN);
@@ -6714,7 +6718,25 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
gimplify_seq_add_stmt (&for_body, gimple_build_assign (decl, var));
- omp_add_variable (gimplify_omp_ctxp, var, GOVD_PRIVATE | GOVD_SEEN);
+ if (simd && TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) == 1)
+ {
+ c2 = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
+ OMP_CLAUSE_LINEAR_NO_COPYIN (c2) = 1;
+ OMP_CLAUSE_LINEAR_NO_COPYOUT (c2) = 1;
+ OMP_CLAUSE_DECL (c2) = var;
+ OMP_CLAUSE_CHAIN (c2) = OMP_FOR_CLAUSES (for_stmt);
+ OMP_FOR_CLAUSES (for_stmt) = c2;
+ omp_add_variable (gimplify_omp_ctxp, var,
+ GOVD_LINEAR | GOVD_EXPLICIT | GOVD_SEEN);
+ if (c == NULL_TREE)
+ {
+ c = c2;
+ c2 = NULL_TREE;
+ }
+ }
+ else
+ omp_add_variable (gimplify_omp_ctxp, var,
+ GOVD_PRIVATE | GOVD_SEEN);
}
else
var = decl;
@@ -6817,13 +6839,22 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
gcc_unreachable ();
}
+ if (c2)
+ {
+ gcc_assert (c);
+ OMP_CLAUSE_LINEAR_STEP (c2) = OMP_CLAUSE_LINEAR_STEP (c);
+ }
+
if ((var != decl || TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) > 1)
&& orig_for_stmt == for_stmt)
{
for (c = OMP_FOR_CLAUSES (for_stmt); c ; c = OMP_CLAUSE_CHAIN (c))
- if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
- && OMP_CLAUSE_DECL (c) == decl
- && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) == NULL)
+ if (((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
+ && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) == NULL)
+ || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
+ && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)
+ && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) == NULL))
+ && OMP_CLAUSE_DECL (c) == decl)
{
t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
@@ -6835,8 +6866,12 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
gcc_assert (TREE_OPERAND (t, 0) == var);
t = build2 (TREE_CODE (t), TREE_TYPE (decl), decl,
TREE_OPERAND (t, 1));
- gimplify_assign (decl, t,
- &OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
+ gimple_seq *seq;
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
+ seq = &OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c);
+ else
+ seq = &OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c);
+ gimplify_assign (decl, t, seq);
}
}
}
diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog
index 966fd425d78..1a863b04dbc 100644
--- a/gcc/go/ChangeLog
+++ b/gcc/go/ChangeLog
@@ -1,3 +1,16 @@
+2014-04-25 Chris Manghane <cmang@google.com>
+
+ * go-gcc.cc: Include "cgraph.h" and "gimplify.h".
+ (Gcc_backend::return_statement): Push and pop function.
+ (Gcc_backend::label): Likewise.
+ (Gcc_backend::function_defer_statement): Likewise.
+ (Gcc_backend::switch_statement): Add function parameter.
+ (Gcc_backend::block): Don't permit function to be NULL.
+ (Gcc_backend::temporary_variable): Change go_assert to
+ gcc_assert.
+ (Gcc_backend::gc_root_variable): New function.
+ (Gcc_backend::write_global_definitions): New function.
+
2014-04-22 Chris Manghane <cmang@google.com>
* go-gcc.cc (Gcc_backend::temporary_variable): Push cfun around
diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc
index 50403e159ef..a0283fe12e0 100644
--- a/gcc/go/go-gcc.cc
+++ b/gcc/go/go-gcc.cc
@@ -29,9 +29,11 @@
#include "stor-layout.h"
#include "varasm.h"
#include "tree-iterator.h"
+#include "cgraph.h"
#include "convert.h"
#include "basic-block.h"
#include "gimple-expr.h"
+#include "gimplify.h"
#include "toplev.h"
#include "output.h"
#include "real.h"
@@ -317,7 +319,7 @@ class Gcc_backend : public Backend
Location);
Bstatement*
- switch_statement(Bexpression* value,
+ switch_statement(Bfunction* function, Bexpression* value,
const std::vector<std::vector<Bexpression*> >& cases,
const std::vector<Bstatement*>& statements,
Location);
@@ -376,6 +378,9 @@ class Gcc_backend : public Backend
Location, Bstatement**);
Bvariable*
+ gc_root_variable(Btype*, Bexpression*);
+
+ Bvariable*
immutable_struct(const std::string&, bool, bool, Btype*, Location);
void
@@ -420,6 +425,12 @@ class Gcc_backend : public Backend
bool
function_set_body(Bfunction* function, Bstatement* code_stmt);
+ void
+ write_global_definitions(const std::vector<Btype*>&,
+ const std::vector<Bexpression*>&,
+ const std::vector<Bfunction*>&,
+ const std::vector<Bvariable*>&);
+
private:
// Make a Bexpression from a tree.
Bexpression*
@@ -1708,6 +1719,7 @@ Gcc_backend::return_statement(Bfunction* bfunction,
tree result = DECL_RESULT(fntree);
if (result == error_mark_node)
return this->error_statement();
+
tree ret;
if (vals.empty())
ret = fold_build1_loc(location.gcc_location(), RETURN_EXPR, void_type_node,
@@ -1731,7 +1743,14 @@ Gcc_backend::return_statement(Bfunction* bfunction,
// statement.
tree stmt_list = NULL_TREE;
tree rettype = TREE_TYPE(result);
+
+ if (DECL_STRUCT_FUNCTION(fntree) == NULL)
+ push_struct_function(fntree);
+ else
+ push_cfun(DECL_STRUCT_FUNCTION(fntree));
tree rettmp = create_tmp_var(rettype, "RESULT");
+ pop_cfun();
+
tree field = TYPE_FIELDS(rettype);
for (std::vector<Bexpression*>::const_iterator p = vals.begin();
p != vals.end();
@@ -1817,6 +1836,7 @@ Gcc_backend::if_statement(Bexpression* condition, Bblock* then_block,
Bstatement*
Gcc_backend::switch_statement(
+ Bfunction* function,
Bexpression* value,
const std::vector<std::vector<Bexpression*> >& cases,
const std::vector<Bstatement*>& statements,
@@ -1824,6 +1844,12 @@ Gcc_backend::switch_statement(
{
gcc_assert(cases.size() == statements.size());
+ tree decl = function->get_tree();
+ if (DECL_STRUCT_FUNCTION(decl) == NULL)
+ push_struct_function(decl);
+ else
+ push_cfun(DECL_STRUCT_FUNCTION(decl));
+
tree stmt_list = NULL_TREE;
std::vector<std::vector<Bexpression*> >::const_iterator pc = cases.begin();
for (std::vector<Bstatement*>::const_iterator ps = statements.begin();
@@ -1863,6 +1889,7 @@ Gcc_backend::switch_statement(
append_to_statement_list(t, &stmt_list);
}
}
+ pop_cfun();
tree tv = value->get_tree();
if (tv == error_mark_node)
@@ -1921,13 +1948,7 @@ Gcc_backend::block(Bfunction* function, Bblock* enclosing,
tree block_tree = make_node(BLOCK);
if (enclosing == NULL)
{
- // FIXME: Permitting FUNCTION to be NULL is a temporary measure
- // until we have a proper representation of the init function.
- tree fndecl;
- if (function == NULL)
- fndecl = current_function_decl;
- else
- fndecl = function->get_tree();
+ tree fndecl = function->get_tree();
gcc_assert(fndecl != NULL_TREE);
// We may have already created a block for local variables when
@@ -1981,7 +2002,6 @@ Gcc_backend::block(Bfunction* function, Bblock* enclosing,
void_type_node, BLOCK_VARS(block_tree),
NULL_TREE, block_tree);
TREE_SIDE_EFFECTS(bind_tree) = 1;
-
return new Bblock(bind_tree);
}
@@ -2213,7 +2233,7 @@ Gcc_backend::temporary_variable(Bfunction* function, Bblock* bblock,
return this->error_variable();
}
- go_assert(function != NULL);
+ gcc_assert(function != NULL);
tree decl = function->get_tree();
tree var;
@@ -2262,6 +2282,28 @@ Gcc_backend::temporary_variable(Bfunction* function, Bblock* bblock,
return new Bvariable(var);
}
+// Make a GC root variable.
+
+Bvariable*
+Gcc_backend::gc_root_variable(Btype* type, Bexpression* init)
+{
+ tree type_tree = type->get_tree();
+ tree init_tree = init->get_tree();
+ if (type_tree == error_mark_node || init_tree == error_mark_node)
+ return this->error_variable();
+
+ tree decl = build_decl(BUILTINS_LOCATION, VAR_DECL,
+ create_tmp_var_name("gc"), type_tree);
+ DECL_EXTERNAL(decl) = 0;
+ TREE_PUBLIC(decl) = 0;
+ TREE_STATIC(decl) = 1;
+ DECL_ARTIFICIAL(decl) = 1;
+ DECL_INITIAL(decl) = init_tree;
+ rest_of_decl_compilation(decl, 1, 0);
+
+ return new Bvariable(decl);
+}
+
// Create a named immutable initialized data structure.
Bvariable*
@@ -2276,9 +2318,9 @@ Gcc_backend::immutable_struct(const std::string& name, bool is_hidden,
get_identifier_from_string(name),
build_qualified_type(type_tree, TYPE_QUAL_CONST));
TREE_STATIC(decl) = 1;
+ TREE_USED(decl) = 1;
TREE_READONLY(decl) = 1;
TREE_CONSTANT(decl) = 1;
- TREE_USED(decl) = 1;
DECL_ARTIFICIAL(decl) = 1;
if (!is_hidden)
TREE_PUBLIC(decl) = 1;
@@ -2368,7 +2410,17 @@ Gcc_backend::label(Bfunction* function, const std::string& name,
{
tree decl;
if (name.empty())
- decl = create_artificial_label(location.gcc_location());
+ {
+ tree func_tree = function->get_tree();
+ if (DECL_STRUCT_FUNCTION(func_tree) == NULL)
+ push_struct_function(func_tree);
+ else
+ push_cfun(DECL_STRUCT_FUNCTION(func_tree));
+
+ decl = create_artificial_label(location.gcc_location());
+
+ pop_cfun();
+ }
else
{
tree id = get_identifier_from_string(name);
@@ -2476,11 +2528,18 @@ Gcc_backend::function_defer_statement(Bfunction* function, Bexpression* undefer,
{
tree undefer_tree = undefer->get_tree();
tree defer_tree = defer->get_tree();
+ tree fntree = function->get_tree();
if (undefer_tree == error_mark_node
- || defer_tree == error_mark_node)
+ || defer_tree == error_mark_node
+ || fntree == error_mark_node)
return this->error_statement();
+ if (DECL_STRUCT_FUNCTION(fntree) == NULL)
+ push_struct_function(fntree);
+ else
+ push_cfun(DECL_STRUCT_FUNCTION(fntree));
+
tree stmt_list = NULL;
Blabel* blabel = this->label(function, "", location);
Bstatement* label_def = this->label_definition_statement(blabel);
@@ -2493,6 +2552,7 @@ Gcc_backend::function_defer_statement(Bfunction* function, Bexpression* undefer,
tree try_catch =
build2(TRY_CATCH_EXPR, void_type_node, undefer_tree, catch_body);
append_to_statement_list(try_catch, &stmt_list);
+ pop_cfun();
return this->make_statement(stmt_list);
}
@@ -2537,6 +2597,88 @@ Gcc_backend::function_set_body(Bfunction* function, Bstatement* code_stmt)
return true;
}
+// Write the definitions for all TYPE_DECLS, CONSTANT_DECLS,
+// FUNCTION_DECLS, and VARIABLE_DECLS declared globally.
+
+void
+Gcc_backend::write_global_definitions(
+ const std::vector<Btype*>& type_decls,
+ const std::vector<Bexpression*>& constant_decls,
+ const std::vector<Bfunction*>& function_decls,
+ const std::vector<Bvariable*>& variable_decls)
+{
+ size_t count_definitions = type_decls.size() + constant_decls.size()
+ + function_decls.size() + variable_decls.size();
+
+ tree* defs = new tree[count_definitions];
+
+ // Convert all non-erroneous declarations into Gimple form.
+ size_t i = 0;
+ for (std::vector<Bvariable*>::const_iterator p = variable_decls.begin();
+ p != variable_decls.end();
+ ++p)
+ {
+ if ((*p)->get_tree() != error_mark_node)
+ {
+ defs[i] = (*p)->get_tree();
+ go_preserve_from_gc(defs[i]);
+ ++i;
+ }
+ }
+
+ for (std::vector<Btype*>::const_iterator p = type_decls.begin();
+ p != type_decls.end();
+ ++p)
+ {
+ tree type_tree = (*p)->get_tree();
+ if (type_tree != error_mark_node
+ && IS_TYPE_OR_DECL_P(type_tree))
+ {
+ defs[i] = TYPE_NAME(type_tree);
+ gcc_assert(defs[i] != NULL);
+ go_preserve_from_gc(defs[i]);
+ ++i;
+ }
+ }
+ for (std::vector<Bexpression*>::const_iterator p = constant_decls.begin();
+ p != constant_decls.end();
+ ++p)
+ {
+ if ((*p)->get_tree() != error_mark_node)
+ {
+ defs[i] = (*p)->get_tree();
+ go_preserve_from_gc(defs[i]);
+ ++i;
+ }
+ }
+ for (std::vector<Bfunction*>::const_iterator p = function_decls.begin();
+ p != function_decls.end();
+ ++p)
+ {
+ tree decl = (*p)->get_tree();
+ if (decl != error_mark_node)
+ {
+ go_preserve_from_gc(decl);
+ gimplify_function_tree(decl);
+ cgraph_finalize_function(decl, true);
+
+ defs[i] = decl;
+ ++i;
+ }
+ }
+
+ // Pass everything back to the middle-end.
+
+ wrapup_global_declarations(defs, i);
+
+ finalize_compilation_unit();
+
+ check_global_declarations(defs, i);
+ emit_debug_global_declarations(defs, i);
+
+ delete[] defs;
+}
+
// The single backend.
static Gcc_backend gcc_backend;
diff --git a/gcc/go/gofrontend/backend.h b/gcc/go/gofrontend/backend.h
index dd76204e70c..aca3dc6f90e 100644
--- a/gcc/go/gofrontend/backend.h
+++ b/gcc/go/gofrontend/backend.h
@@ -406,9 +406,9 @@ class Backend
// integers, then STATEMENTS[i] is executed. STATEMENTS[i] will
// either end with a goto statement or will fall through into
// STATEMENTS[i + 1]. CASES[i] is empty for the default clause,
- // which need not be last.
+ // which need not be last. FUNCTION is the current function.
virtual Bstatement*
- switch_statement(Bexpression* value,
+ switch_statement(Bfunction* function, Bexpression* value,
const std::vector<std::vector<Bexpression*> >& cases,
const std::vector<Bstatement*>& statements,
Location) = 0;
@@ -534,6 +534,12 @@ class Backend
bool address_is_taken, Location location,
Bstatement** pstatement) = 0;
+ // Create a GC root variable. TYPE is the __go_gc_root_list struct described
+ // in Gogo::register_gc_vars. INIT is the composite literal consisting of a
+ // pointer to the next GC root and the global variables registered.
+ virtual Bvariable*
+ gc_root_variable(Btype* type, Bexpression* init) = 0;
+
// Create a named immutable initialized data structure. This is
// used for type descriptors, map descriptors, and function
// descriptors. This returns a Bvariable because it corresponds to
@@ -653,6 +659,16 @@ class Backend
// true on success, false on failure.
virtual bool
function_set_body(Bfunction* function, Bstatement* code_stmt) = 0;
+
+ // Utility.
+
+ // Write the definitions for all TYPE_DECLS, CONSTANT_DECLS,
+ // FUNCTION_DECLS, and VARIABLE_DECLS declared globally.
+ virtual void
+ write_global_definitions(const std::vector<Btype*>& type_decls,
+ const std::vector<Bexpression*>& constant_decls,
+ const std::vector<Bfunction*>& function_decls,
+ const std::vector<Bvariable*>& variable_decls) = 0;
};
// The backend interface has to define this function.
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 74ae9ddcd7d..27562639176 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -3578,127 +3578,7 @@ Expression::make_unsafe_cast(Type* type, Expression* expr,
return new Unsafe_type_conversion_expression(type, expr, location);
}
-// Unary expressions.
-
-class Unary_expression : public Expression
-{
- public:
- Unary_expression(Operator op, Expression* expr, Location location)
- : Expression(EXPRESSION_UNARY, location),
- op_(op), escapes_(true), create_temp_(false), expr_(expr),
- issue_nil_check_(false)
- { }
-
- // Return the operator.
- Operator
- op() const
- { return this->op_; }
-
- // Return the operand.
- Expression*
- operand() const
- { return this->expr_; }
-
- // Record that an address expression does not escape.
- void
- set_does_not_escape()
- {
- go_assert(this->op_ == OPERATOR_AND);
- this->escapes_ = false;
- }
-
- // Record that this is an address expression which should create a
- // temporary variable if necessary. This is used for method calls.
- void
- set_create_temp()
- {
- go_assert(this->op_ == OPERATOR_AND);
- this->create_temp_ = true;
- }
-
- // Apply unary opcode OP to UNC, setting NC. Return true if this
- // could be done, false if not. Issue errors for overflow.
- static bool
- eval_constant(Operator op, const Numeric_constant* unc,
- Location, Numeric_constant* nc);
-
- static Expression*
- do_import(Import*);
-
- protected:
- int
- do_traverse(Traverse* traverse)
- { return Expression::traverse(&this->expr_, traverse); }
-
- Expression*
- do_lower(Gogo*, Named_object*, Statement_inserter*, int);
-
- Expression*
- do_flatten(Gogo*, Named_object*, Statement_inserter*);
-
- bool
- do_is_constant() const;
-
- bool
- do_is_immutable() const
- { return this->expr_->is_immutable()
- || (this->op_ == OPERATOR_AND && this->expr_->is_variable()); }
-
- bool
- do_numeric_constant_value(Numeric_constant*) const;
-
- Type*
- do_type();
-
- void
- do_determine_type(const Type_context*);
-
- void
- do_check_types(Gogo*);
-
- Expression*
- do_copy()
- {
- return Expression::make_unary(this->op_, this->expr_->copy(),
- this->location());
- }
-
- bool
- do_must_eval_subexpressions_in_order(int*) const
- { return this->op_ == OPERATOR_MULT; }
-
- bool
- do_is_addressable() const
- { return this->op_ == OPERATOR_MULT; }
-
- tree
- do_get_tree(Translate_context*);
-
- void
- do_export(Export*) const;
-
- void
- do_dump_expression(Ast_dump_context*) const;
-
- void
- do_issue_nil_check()
- { this->issue_nil_check_ = (this->op_ == OPERATOR_MULT); }
-
- private:
- // The unary operator to apply.
- Operator op_;
- // Normally true. False if this is an address expression which does
- // not escape the current function.
- bool escapes_;
- // True if this is an address expression which should create a
- // temporary variable if necessary.
- bool create_temp_;
- // The operand.
- Expression* expr_;
- // Whether or not to issue a nil check for this expression if its address
- // is being taken.
- bool issue_nil_check_;
-};
+// Class Unary_expression.
// If we are taking the address of a composite literal, and the
// contents are not constant, then we want to make a heap expression
@@ -4214,11 +4094,18 @@ Unary_expression::do_get_tree(Translate_context* context)
}
}
- // Build a decl for a constant constructor.
- if ((this->expr_->is_composite_literal()
+ if (this->is_gc_root_)
+ {
+ // Build a decl for a GC root variable. GC roots are mutable, so they
+ // cannot be represented as an immutable_struct in the backend.
+ Bvariable* gc_root = gogo->backend()->gc_root_variable(btype, bexpr);
+ bexpr = gogo->backend()->var_expression(gc_root, loc);
+ }
+ else if ((this->expr_->is_composite_literal()
|| this->expr_->string_expression() != NULL)
&& this->expr_->is_immutable())
{
+ // Build a decl for a constant constructor.
static unsigned int counter;
char buf[100];
snprintf(buf, sizeof buf, "C%u", counter);
@@ -12508,6 +12395,14 @@ Fixed_array_construction_expression::do_get_tree(Translate_context* context)
return expr_to_tree(this->get_constructor(context, btype));
}
+Expression*
+Expression::make_array_composite_literal(Type* type, Expression_list* vals,
+ Location location)
+{
+ go_assert(type->array_type() != NULL && !type->is_slice_type());
+ return new Fixed_array_construction_expression(type, NULL, vals, location);
+}
+
// Construct a slice.
class Slice_construction_expression : public Array_construction_expression
diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h
index dc9ad71c820..0936e00bae0 100644
--- a/gcc/go/gofrontend/expressions.h
+++ b/gcc/go/gofrontend/expressions.h
@@ -30,6 +30,7 @@ class Var_expression;
class Temporary_reference_expression;
class Set_and_use_temporary_expression;
class String_expression;
+class Unary_expression;
class Binary_expression;
class Call_expression;
class Func_expression;
@@ -327,6 +328,10 @@ class Expression
static Expression*
make_struct_composite_literal(Type*, Expression_list*, Location);
+ // Make an array composite literal.
+ static Expression*
+ make_array_composite_literal(Type*, Expression_list*, Location);
+
// Make a slice composite literal.
static Expression*
make_slice_composite_literal(Type*, Expression_list*, Location);
@@ -533,6 +538,12 @@ class Expression
Expression*
deref();
+ // If this is a unary expression, return the Unary_expression
+ // structure. Otherwise return NULL.
+ Unary_expression*
+ unary_expression()
+ { return this->convert<Unary_expression, EXPRESSION_UNARY>(); }
+
// If this is a binary expression, return the Binary_expression
// structure. Otherwise return NULL.
Binary_expression*
@@ -1286,6 +1297,143 @@ class String_expression : public Expression
Type* type_;
};
+// A Unary expression.
+
+class Unary_expression : public Expression
+{
+ public:
+ Unary_expression(Operator op, Expression* expr, Location location)
+ : Expression(EXPRESSION_UNARY, location),
+ op_(op), escapes_(true), create_temp_(false), is_gc_root_(false),
+ expr_(expr), issue_nil_check_(false)
+ { }
+
+ // Return the operator.
+ Operator
+ op() const
+ { return this->op_; }
+
+ // Return the operand.
+ Expression*
+ operand() const
+ { return this->expr_; }
+
+ // Record that an address expression does not escape.
+ void
+ set_does_not_escape()
+ {
+ go_assert(this->op_ == OPERATOR_AND);
+ this->escapes_ = false;
+ }
+
+ // Record that this is an address expression which should create a
+ // temporary variable if necessary. This is used for method calls.
+ void
+ set_create_temp()
+ {
+ go_assert(this->op_ == OPERATOR_AND);
+ this->create_temp_ = true;
+ }
+
+ // Record that this is an address expression of a GC root, which is a
+ // mutable composite literal. This used for registering GC variables.
+ void
+ set_is_gc_root()
+ {
+ go_assert(this->op_ == OPERATOR_AND);
+ this->is_gc_root_ = true;
+ }
+
+ // Apply unary opcode OP to UNC, setting NC. Return true if this
+ // could be done, false if not. Issue errors for overflow.
+ static bool
+ eval_constant(Operator op, const Numeric_constant* unc,
+ Location, Numeric_constant* nc);
+
+ static Expression*
+ do_import(Import*);
+
+ protected:
+ int
+ do_traverse(Traverse* traverse)
+ { return Expression::traverse(&this->expr_, traverse); }
+
+ Expression*
+ do_lower(Gogo*, Named_object*, Statement_inserter*, int);
+
+ Expression*
+ do_flatten(Gogo*, Named_object*, Statement_inserter*);
+
+ bool
+ do_is_constant() const;
+
+ bool
+ do_is_immutable() const
+ {
+ return (this->expr_->is_immutable()
+ || (this->op_ == OPERATOR_AND && this->expr_->is_variable()));
+ }
+
+ bool
+ do_numeric_constant_value(Numeric_constant*) const;
+
+ Type*
+ do_type();
+
+ void
+ do_determine_type(const Type_context*);
+
+ void
+ do_check_types(Gogo*);
+
+ Expression*
+ do_copy()
+ {
+ return Expression::make_unary(this->op_, this->expr_->copy(),
+ this->location());
+ }
+
+ bool
+ do_must_eval_subexpressions_in_order(int*) const
+ { return this->op_ == OPERATOR_MULT; }
+
+ bool
+ do_is_addressable() const
+ { return this->op_ == OPERATOR_MULT; }
+
+ tree
+ do_get_tree(Translate_context*);
+
+ void
+ do_export(Export*) const;
+
+ void
+ do_dump_expression(Ast_dump_context*) const;
+
+ void
+ do_issue_nil_check()
+ { this->issue_nil_check_ = (this->op_ == OPERATOR_MULT); }
+
+ private:
+ // The unary operator to apply.
+ Operator op_;
+ // Normally true. False if this is an address expression which does
+ // not escape the current function.
+ bool escapes_;
+ // True if this is an address expression which should create a
+ // temporary variable if necessary.
+ bool create_temp_;
+ // True if this is an address expression for a GC root. A GC root is a
+ // special struct composite literal that is mutable when addressed, meaning
+ // it cannot be represented as an immutable_struct in the backend.
+ bool is_gc_root_;
+ // The operand.
+ Expression* expr_;
+ // Whether or not to issue a nil check for this expression if its address
+ // is being taken.
+ bool issue_nil_check_;
+};
+
// A binary expression.
class Binary_expression : public Expression
diff --git a/gcc/go/gofrontend/gogo-tree.cc b/gcc/go/gofrontend/gogo-tree.cc
index c00e7d16011..6b19a1d82e1 100644
--- a/gcc/go/gofrontend/gogo-tree.cc
+++ b/gcc/go/gofrontend/gogo-tree.cc
@@ -236,830 +236,6 @@ Gogo::define_builtin_function_trees()
false);
}
-// Add statements to INIT_STMT_LIST which run the initialization
-// functions for imported packages. This is only used for the "main"
-// package.
-
-void
-Gogo::init_imports(tree* init_stmt_list)
-{
- go_assert(this->is_main_package());
-
- if (this->imported_init_fns_.empty())
- return;
-
- tree fntype = build_function_type(void_type_node, void_list_node);
-
- // We must call them in increasing priority order.
- std::vector<Import_init> v;
- for (std::set<Import_init>::const_iterator p =
- this->imported_init_fns_.begin();
- p != this->imported_init_fns_.end();
- ++p)
- v.push_back(*p);
- std::sort(v.begin(), v.end());
-
- for (std::vector<Import_init>::const_iterator p = v.begin();
- p != v.end();
- ++p)
- {
- std::string user_name = p->package_name() + ".init";
- tree decl = build_decl(UNKNOWN_LOCATION, FUNCTION_DECL,
- get_identifier_from_string(user_name),
- fntype);
- const std::string& init_name(p->init_name());
- SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(init_name));
- TREE_PUBLIC(decl) = 1;
- DECL_EXTERNAL(decl) = 1;
- append_to_statement_list(build_call_expr(decl, 0), init_stmt_list);
- }
-}
-
-// Register global variables with the garbage collector. We need to
-// register all variables which can hold a pointer value. They become
-// roots during the mark phase. We build a struct that is easy to
-// hook into a list of roots.
-
-// struct __go_gc_root_list
-// {
-// struct __go_gc_root_list* __next;
-// struct __go_gc_root
-// {
-// void* __decl;
-// size_t __size;
-// } __roots[];
-// };
-
-// The last entry in the roots array has a NULL decl field.
-
-void
-Gogo::register_gc_vars(const std::vector<Named_object*>& var_gc,
- tree* init_stmt_list)
-{
- if (var_gc.empty())
- return;
-
- size_t count = var_gc.size();
-
- tree root_type = Gogo::builtin_struct(NULL, "__go_gc_root", NULL_TREE, 2,
- "__next",
- ptr_type_node,
- "__size",
- sizetype);
-
- tree index_type = build_index_type(size_int(count));
- tree array_type = build_array_type(root_type, index_type);
-
- tree root_list_type = make_node(RECORD_TYPE);
- root_list_type = Gogo::builtin_struct(NULL, "__go_gc_root_list",
- root_list_type, 2,
- "__next",
- build_pointer_type(root_list_type),
- "__roots",
- array_type);
-
- // Build an initialier for the __roots array.
-
- vec<constructor_elt, va_gc> *roots_init;
- vec_alloc(roots_init, count + 1);
-
- size_t i = 0;
- for (std::vector<Named_object*>::const_iterator p = var_gc.begin();
- p != var_gc.end();
- ++p, ++i)
- {
- vec<constructor_elt, va_gc> *init;
- vec_alloc(init, 2);
-
- constructor_elt empty = {NULL, NULL};
- constructor_elt* elt = init->quick_push(empty);
- tree field = TYPE_FIELDS(root_type);
- elt->index = field;
- Bvariable* bvar = (*p)->get_backend_variable(this, NULL);
- tree decl = var_to_tree(bvar);
- go_assert(TREE_CODE(decl) == VAR_DECL);
- elt->value = build_fold_addr_expr(decl);
-
- elt = init->quick_push(empty);
- field = DECL_CHAIN(field);
- elt->index = field;
- elt->value = DECL_SIZE_UNIT(decl);
-
- elt = roots_init->quick_push(empty);
- elt->index = size_int(i);
- elt->value = build_constructor(root_type, init);
- }
-
- // The list ends with a NULL entry.
-
- vec<constructor_elt, va_gc> *init;
- vec_alloc(init, 2);
-
- constructor_elt empty = {NULL, NULL};
- constructor_elt* elt = init->quick_push(empty);
- tree field = TYPE_FIELDS(root_type);
- elt->index = field;
- elt->value = fold_convert(TREE_TYPE(field), null_pointer_node);
-
- elt = init->quick_push(empty);
- field = DECL_CHAIN(field);
- elt->index = field;
- elt->value = size_zero_node;
-
- elt = roots_init->quick_push(empty);
- elt->index = size_int(i);
- elt->value = build_constructor(root_type, init);
-
- // Build a constructor for the struct.
-
- vec<constructor_elt, va_gc> *root_list_init;
- vec_alloc(root_list_init, 2);
-
- elt = root_list_init->quick_push(empty);
- field = TYPE_FIELDS(root_list_type);
- elt->index = field;
- elt->value = fold_convert(TREE_TYPE(field), null_pointer_node);
-
- elt = root_list_init->quick_push(empty);
- field = DECL_CHAIN(field);
- elt->index = field;
- elt->value = build_constructor(array_type, roots_init);
-
- // Build a decl to register.
-
- tree decl = build_decl(BUILTINS_LOCATION, VAR_DECL,
- create_tmp_var_name("gc"), root_list_type);
- DECL_EXTERNAL(decl) = 0;
- TREE_PUBLIC(decl) = 0;
- TREE_STATIC(decl) = 1;
- DECL_ARTIFICIAL(decl) = 1;
- DECL_INITIAL(decl) = build_constructor(root_list_type, root_list_init);
- rest_of_decl_compilation(decl, 1, 0);
-
- static tree register_gc_fndecl;
- tree call = Gogo::call_builtin(&register_gc_fndecl,
- Linemap::predeclared_location(),
- "__go_register_gc_roots",
- 1,
- void_type_node,
- build_pointer_type(root_list_type),
- build_fold_addr_expr(decl));
- if (call != error_mark_node)
- append_to_statement_list(call, init_stmt_list);
-}
-
-// Create the magic initialization function. INIT_STMT_LIST is the
-// code that it needs to run.
-
-void
-Gogo::write_initialization_function(Named_object* initfn, tree init_stmt_list)
-{
- // Make sure that we thought we needed an initialization function,
- // as otherwise we will not have reported it in the export data.
- go_assert(this->is_main_package() || this->need_init_fn_);
-
- if (initfn == NULL)
- initfn = this->initialization_function_decl();
-
- Bfunction* fndecl = initfn->func_value()->get_or_make_decl(this, initfn);
- Location loc = this->package_->location();
- std::vector<Bvariable*> vars;
- this->backend()->block(fndecl, NULL, vars, loc, loc);
-
- if (!this->backend()->function_set_body(fndecl, tree_to_stat(init_stmt_list)))
- {
- go_assert(saw_errors());
- return;
- }
- gimplify_function_tree(function_to_tree(fndecl));
- cgraph_add_new_function(function_to_tree(fndecl), false);
-}
-
-// Search for references to VAR in any statements or called functions.
-
-class Find_var : public Traverse
-{
- public:
- // A hash table we use to avoid looping. The index is the name of a
- // named object. We only look through objects defined in this
- // package.
- typedef Unordered_set(const void*) Seen_objects;
-
- Find_var(Named_object* var, Seen_objects* seen_objects)
- : Traverse(traverse_expressions),
- var_(var), seen_objects_(seen_objects), found_(false)
- { }
-
- // Whether the variable was found.
- bool
- found() const
- { return this->found_; }
-
- int
- expression(Expression**);
-
- private:
- // The variable we are looking for.
- Named_object* var_;
- // Names of objects we have already seen.
- Seen_objects* seen_objects_;
- // True if the variable was found.
- bool found_;
-};
-
-// See if EXPR refers to VAR, looking through function calls and
-// variable initializations.
-
-int
-Find_var::expression(Expression** pexpr)
-{
- Expression* e = *pexpr;
-
- Var_expression* ve = e->var_expression();
- if (ve != NULL)
- {
- Named_object* v = ve->named_object();
- if (v == this->var_)
- {
- this->found_ = true;
- return TRAVERSE_EXIT;
- }
-
- if (v->is_variable() && v->package() == NULL)
- {
- Expression* init = v->var_value()->init();
- if (init != NULL)
- {
- std::pair<Seen_objects::iterator, bool> ins =
- this->seen_objects_->insert(v);
- if (ins.second)
- {
- // This is the first time we have seen this name.
- if (Expression::traverse(&init, this) == TRAVERSE_EXIT)
- return TRAVERSE_EXIT;
- }
- }
- }
- }
-
- // We traverse the code of any function we see. Note that this
- // means that we will traverse the code of a function whose address
- // is taken even if it is not called.
- Func_expression* fe = e->func_expression();
- if (fe != NULL)
- {
- const Named_object* f = fe->named_object();
- if (f->is_function() && f->package() == NULL)
- {
- std::pair<Seen_objects::iterator, bool> ins =
- this->seen_objects_->insert(f);
- if (ins.second)
- {
- // This is the first time we have seen this name.
- if (f->func_value()->block()->traverse(this) == TRAVERSE_EXIT)
- return TRAVERSE_EXIT;
- }
- }
- }
-
- Temporary_reference_expression* tre = e->temporary_reference_expression();
- if (tre != NULL)
- {
- Temporary_statement* ts = tre->statement();
- Expression* init = ts->init();
- if (init != NULL)
- {
- std::pair<Seen_objects::iterator, bool> ins =
- this->seen_objects_->insert(ts);
- if (ins.second)
- {
- // This is the first time we have seen this temporary
- // statement.
- if (Expression::traverse(&init, this) == TRAVERSE_EXIT)
- return TRAVERSE_EXIT;
- }
- }
- }
-
- return TRAVERSE_CONTINUE;
-}
-
-// Return true if EXPR, PREINIT, or DEP refers to VAR.
-
-static bool
-expression_requires(Expression* expr, Block* preinit, Named_object* dep,
- Named_object* var)
-{
- Find_var::Seen_objects seen_objects;
- Find_var find_var(var, &seen_objects);
- if (expr != NULL)
- Expression::traverse(&expr, &find_var);
- if (preinit != NULL)
- preinit->traverse(&find_var);
- if (dep != NULL)
- {
- Expression* init = dep->var_value()->init();
- if (init != NULL)
- Expression::traverse(&init, &find_var);
- if (dep->var_value()->has_pre_init())
- dep->var_value()->preinit()->traverse(&find_var);
- }
-
- return find_var.found();
-}
-
-// Sort variable initializations. If the initialization expression
-// for variable A refers directly or indirectly to the initialization
-// expression for variable B, then we must initialize B before A.
-
-class Var_init
-{
- public:
- Var_init()
- : var_(NULL), init_(NULL)
- { }
-
- Var_init(Named_object* var, Bstatement* init)
- : var_(var), init_(init)
- { }
-
- // Return the variable.
- Named_object*
- var() const
- { return this->var_; }
-
- // Return the initialization expression.
- Bstatement*
- init() const
- { return this->init_; }
-
- private:
- // The variable being initialized.
- Named_object* var_;
- // The initialization statement.
- Bstatement* init_;
-};
-
-typedef std::list<Var_init> Var_inits;
-
-// Sort the variable initializations. The rule we follow is that we
-// emit them in the order they appear in the array, except that if the
-// initialization expression for a variable V1 depends upon another
-// variable V2 then we initialize V1 after V2.
-
-static void
-sort_var_inits(Gogo* gogo, Var_inits* var_inits)
-{
- typedef std::pair<Named_object*, Named_object*> No_no;
- typedef std::map<No_no, bool> Cache;
- Cache cache;
-
- Var_inits ready;
- while (!var_inits->empty())
- {
- Var_inits::iterator p1 = var_inits->begin();
- Named_object* var = p1->var();
- Expression* init = var->var_value()->init();
- Block* preinit = var->var_value()->preinit();
- Named_object* dep = gogo->var_depends_on(var->var_value());
-
- // Start walking through the list to see which variables VAR
- // needs to wait for.
- Var_inits::iterator p2 = p1;
- ++p2;
-
- for (; p2 != var_inits->end(); ++p2)
- {
- Named_object* p2var = p2->var();
- No_no key(var, p2var);
- std::pair<Cache::iterator, bool> ins =
- cache.insert(std::make_pair(key, false));
- if (ins.second)
- ins.first->second = expression_requires(init, preinit, dep, p2var);
- if (ins.first->second)
- {
- // Check for cycles.
- key = std::make_pair(p2var, var);
- ins = cache.insert(std::make_pair(key, false));
- if (ins.second)
- ins.first->second =
- expression_requires(p2var->var_value()->init(),
- p2var->var_value()->preinit(),
- gogo->var_depends_on(p2var->var_value()),
- var);
- if (ins.first->second)
- {
- error_at(var->location(),
- ("initialization expressions for %qs and "
- "%qs depend upon each other"),
- var->message_name().c_str(),
- p2var->message_name().c_str());
- inform(p2->var()->location(), "%qs defined here",
- p2var->message_name().c_str());
- p2 = var_inits->end();
- }
- else
- {
- // We can't emit P1 until P2 is emitted. Move P1.
- Var_inits::iterator p3 = p2;
- ++p3;
- var_inits->splice(p3, *var_inits, p1);
- }
- break;
- }
- }
-
- if (p2 == var_inits->end())
- {
- // VAR does not depends upon any other initialization expressions.
-
- // Check for a loop of VAR on itself. We only do this if
- // INIT is not NULL and there is no dependency; when INIT is
- // NULL, it means that PREINIT sets VAR, which we will
- // interpret as a loop.
- if (init != NULL && dep == NULL
- && expression_requires(init, preinit, NULL, var))
- error_at(var->location(),
- "initialization expression for %qs depends upon itself",
- var->message_name().c_str());
- ready.splice(ready.end(), *var_inits, p1);
- }
- }
-
- // Now READY is the list in the desired initialization order.
- var_inits->swap(ready);
-}
-
-// Write out the global definitions.
-
-void
-Gogo::write_globals()
-{
- this->build_interface_method_tables();
-
- Bindings* bindings = this->current_bindings();
-
- for (Bindings::const_declarations_iterator p = bindings->begin_declarations();
- p != bindings->end_declarations();
- ++p)
- {
- // If any function declarations needed a descriptor, make sure
- // we build it.
- Named_object* no = p->second;
- if (no->is_function_declaration())
- no->func_declaration_value()->build_backend_descriptor(this);
- }
-
- size_t count_definitions = bindings->size_definitions();
- size_t count = count_definitions;
-
- tree* vec = new tree[count];
-
- Named_object* init_fndecl = NULL;
- tree init_stmt_list = NULL_TREE;
-
- if (this->is_main_package())
- this->init_imports(&init_stmt_list);
-
- // A list of variable initializations.
- Var_inits var_inits;
-
- // A list of variables which need to be registered with the garbage
- // collector.
- std::vector<Named_object*> var_gc;
- var_gc.reserve(count);
-
- tree var_init_stmt_list = NULL_TREE;
- size_t i = 0;
- for (Bindings::const_definitions_iterator p = bindings->begin_definitions();
- p != bindings->end_definitions();
- ++p, ++i)
- {
- Named_object* no = *p;
-
- go_assert(i < count);
-
- go_assert(!no->is_type_declaration() && !no->is_function_declaration());
- // There is nothing to do for a package.
- if (no->is_package())
- {
- --i;
- --count;
- continue;
- }
-
- // There is nothing to do for an object which was imported from
- // a different package into the global scope.
- if (no->package() != NULL)
- {
- --i;
- --count;
- continue;
- }
-
- // Skip blank named functions and constants.
- if ((no->is_function() && no->func_value()->is_sink())
- || (no->is_const() && no->const_value()->is_sink()))
- {
- --i;
- --count;
- continue;
- }
-
- // There is nothing useful we can output for constants which
- // have ideal or non-integral type.
- if (no->is_const())
- {
- Type* type = no->const_value()->type();
- if (type == NULL)
- type = no->const_value()->expr()->type();
- if (type->is_abstract() || type->integer_type() == NULL)
- {
- --i;
- --count;
- continue;
- }
- }
-
- if (!no->is_variable())
- {
- vec[i] = no->get_tree(this, NULL);
- if (vec[i] == error_mark_node)
- {
- go_assert(saw_errors());
- --i;
- --count;
- continue;
- }
- }
- else
- {
- Bvariable* var = no->get_backend_variable(this, NULL);
- vec[i] = var_to_tree(var);
- if (vec[i] == error_mark_node)
- {
- go_assert(saw_errors());
- --i;
- --count;
- continue;
- }
-
- // Check for a sink variable, which may be used to run an
- // initializer purely for its side effects.
- bool is_sink = no->name()[0] == '_' && no->name()[1] == '.';
-
- Bstatement* var_init_stmt = NULL;
- if (!no->var_value()->has_pre_init())
- {
- Bexpression* var_binit = no->var_value()->get_init(this, NULL);
- if (var_binit == NULL)
- ;
- else if (TREE_CONSTANT(expr_to_tree(var_binit)))
- {
- if (expression_requires(no->var_value()->init(), NULL,
- this->var_depends_on(no->var_value()),
- no))
- error_at(no->location(),
- "initialization expression for %qs depends "
- "upon itself",
- no->message_name().c_str());
- this->backend()->global_variable_set_init(var, var_binit);
- }
- else if (is_sink)
- var_init_stmt =
- this->backend()->expression_statement(var_binit);
- else
- {
- Location loc = no->var_value()->location();
- Bexpression* var_expr =
- this->backend()->var_expression(var, loc);
- var_init_stmt =
- this->backend()->assignment_statement(var_expr, var_binit,
- loc);
- }
- }
- else
- {
- // We are going to create temporary variables which
- // means that we need an fndecl.
- if (init_fndecl == NULL)
- init_fndecl = this->initialization_function_decl();
-
- Bvariable* var_decl = is_sink ? NULL : var;
- var_init_stmt =
- no->var_value()->get_init_block(this, init_fndecl, var_decl);
- }
-
- if (var_init_stmt != NULL)
- {
- if (no->var_value()->init() == NULL
- && !no->var_value()->has_pre_init())
- append_to_statement_list(stat_to_tree(var_init_stmt),
- &var_init_stmt_list);
- else
- var_inits.push_back(Var_init(no, var_init_stmt));
- }
- else if (this->var_depends_on(no->var_value()) != NULL)
- {
- // This variable is initialized from something that is
- // not in its init or preinit. This variable needs to
- // participate in dependency analysis sorting, in case
- // some other variable depends on this one.
- Btype* int_btype =
- Type::lookup_integer_type("int")->get_backend(this);
- Bexpression* zero = this->backend()->zero_expression(int_btype);
- Bstatement* zero_stmt =
- this->backend()->expression_statement(zero);
- var_inits.push_back(Var_init(no, zero_stmt));
- }
-
- if (!is_sink && no->var_value()->type()->has_pointer())
- var_gc.push_back(no);
- }
- }
-
- // Register global variables with the garbage collector.
- this->register_gc_vars(var_gc, &init_stmt_list);
-
- // Simple variable initializations, after all variables are
- // registered.
- append_to_statement_list(var_init_stmt_list, &init_stmt_list);
-
- // Complex variable initializations, first sorting them into a
- // workable order.
- if (!var_inits.empty())
- {
- sort_var_inits(this, &var_inits);
- for (Var_inits::const_iterator p = var_inits.begin();
- p != var_inits.end();
- ++p)
- append_to_statement_list(stat_to_tree(p->init()), &init_stmt_list);
- }
-
- // After all the variables are initialized, call the "init"
- // functions if there are any.
- for (std::vector<Named_object*>::const_iterator p =
- this->init_functions_.begin();
- p != this->init_functions_.end();
- ++p)
- {
- tree decl = (*p)->get_tree(this, NULL);
- tree call = build_call_expr(decl, 0);
- append_to_statement_list(call, &init_stmt_list);
- }
-
- // Set up a magic function to do all the initialization actions.
- // This will be called if this package is imported.
- if (init_stmt_list != NULL
- || this->need_init_fn_
- || this->is_main_package())
- this->write_initialization_function(init_fndecl, init_stmt_list);
-
- // We should not have seen any new bindings created during the
- // conversion.
- go_assert(count_definitions == this->current_bindings()->size_definitions());
-
- // Pass everything back to the middle-end.
-
- wrapup_global_declarations(vec, count);
-
- finalize_compilation_unit();
-
- check_global_declarations(vec, count);
- emit_debug_global_declarations(vec, count);
-
- delete[] vec;
-}
-
-// Get a tree for a named object.
-
-tree
-Named_object::get_tree(Gogo* gogo, Named_object* function)
-{
- if (this->tree_ != NULL_TREE)
- return this->tree_;
-
- if (Gogo::is_erroneous_name(this->name_))
- {
- this->tree_ = error_mark_node;
- return error_mark_node;
- }
-
- tree decl;
- switch (this->classification_)
- {
- case NAMED_OBJECT_CONST:
- {
- Translate_context subcontext(gogo, function, NULL, NULL);
- Type* type = this->u_.const_value->type();
- Location loc = this->location();
-
- Expression* const_ref = Expression::make_const_reference(this, loc);
- Bexpression* const_decl =
- tree_to_expr(const_ref->get_tree(&subcontext));
- if (type != NULL && type->is_numeric_type())
- {
- Btype* btype = type->get_backend(gogo);
- std::string name = this->get_id(gogo);
- const_decl =
- gogo->backend()->named_constant_expression(btype, name,
- const_decl, loc);
- }
- decl = expr_to_tree(const_decl);
- }
- break;
-
- case NAMED_OBJECT_TYPE:
- {
- Named_type* named_type = this->u_.type_value;
- tree type_tree = type_to_tree(named_type->get_backend(gogo));
- if (type_tree == error_mark_node)
- decl = error_mark_node;
- else
- {
- decl = TYPE_NAME(type_tree);
- go_assert(decl != NULL_TREE);
-
- // We need to produce a type descriptor for every named
- // type, and for a pointer to every named type, since
- // other files or packages might refer to them. We need
- // to do this even for hidden types, because they might
- // still be returned by some function. Simply calling the
- // type_descriptor method is enough to create the type
- // descriptor, even though we don't do anything with it.
- if (this->package_ == NULL)
- {
- named_type->
- type_descriptor_pointer(gogo,
- Linemap::predeclared_location());
- Type* pn = Type::make_pointer_type(named_type);
- pn->type_descriptor_pointer(gogo,
- Linemap::predeclared_location());
- }
- }
- }
- break;
-
- case NAMED_OBJECT_TYPE_DECLARATION:
- error("reference to undefined type %qs",
- this->message_name().c_str());
- return error_mark_node;
-
- case NAMED_OBJECT_VAR:
- case NAMED_OBJECT_RESULT_VAR:
- case NAMED_OBJECT_SINK:
- go_unreachable();
-
- case NAMED_OBJECT_FUNC:
- {
- Function* func = this->u_.func_value;
- decl = function_to_tree(func->get_or_make_decl(gogo, this));
- if (decl != error_mark_node)
- {
- if (func->block() != NULL)
- {
- if (DECL_STRUCT_FUNCTION(decl) == NULL)
- push_struct_function(decl);
- else
- push_cfun(DECL_STRUCT_FUNCTION(decl));
-
- cfun->function_start_locus = func->location().gcc_location();
- cfun->function_end_locus =
- func->block()->end_location().gcc_location();
-
- func->build(gogo, this);
-
- gimplify_function_tree(decl);
-
- cgraph_finalize_function(decl, true);
-
- pop_cfun();
- }
- }
- }
- break;
-
- case NAMED_OBJECT_ERRONEOUS:
- decl = error_mark_node;
- break;
-
- default:
- go_unreachable();
- }
-
- if (TREE_TYPE(decl) == error_mark_node)
- decl = error_mark_node;
-
- tree ret = decl;
-
- this->tree_ = ret;
-
- if (ret != error_mark_node)
- go_preserve_from_gc(ret);
-
- return ret;
-}
-
// Get the backend representation.
Bfunction*
@@ -1106,15 +282,6 @@ Function_declaration::get_or_make_decl(Gogo* gogo, Named_object* no)
return this->fndecl_;
}
-// Return the function's decl after it has been built.
-
-tree
-Function::get_decl() const
-{
- go_assert(this->fndecl_ != NULL);
- return function_to_tree(this->fndecl_);
-}
-
// Build the descriptor for a function declaration. This won't
// necessarily happen if the package has just a declaration for the
// function and no other reference to it, but we may still need the
@@ -1214,55 +381,6 @@ go_type_for_mode(enum machine_mode mode, int unsignedp)
return NULL_TREE;
}
-// Build a builtin struct with a list of fields. The name is
-// STRUCT_NAME. STRUCT_TYPE is NULL_TREE or an empty RECORD_TYPE
-// node; this exists so that the struct can have fields which point to
-// itself. If PTYPE is not NULL, store the result in *PTYPE. There
-// are NFIELDS fields. Each field is a name (a const char*) followed
-// by a type (a tree).
-
-tree
-Gogo::builtin_struct(tree* ptype, const char* struct_name, tree struct_type,
- int nfields, ...)
-{
- if (ptype != NULL && *ptype != NULL_TREE)
- return *ptype;
-
- va_list ap;
- va_start(ap, nfields);
-
- tree fields = NULL_TREE;
- for (int i = 0; i < nfields; ++i)
- {
- const char* field_name = va_arg(ap, const char*);
- tree type = va_arg(ap, tree);
- if (type == error_mark_node)
- {
- if (ptype != NULL)
- *ptype = error_mark_node;
- return error_mark_node;
- }
- tree field = build_decl(BUILTINS_LOCATION, FIELD_DECL,
- get_identifier(field_name), type);
- DECL_CHAIN(field) = fields;
- fields = field;
- }
-
- va_end(ap);
-
- if (struct_type == NULL_TREE)
- struct_type = make_node(RECORD_TYPE);
- finish_builtin_struct(struct_type, struct_name, fields, NULL_TREE);
-
- if (ptype != NULL)
- {
- go_preserve_from_gc(struct_type);
- *ptype = struct_type;
- }
-
- return struct_type;
-}
-
// Build a constructor for a slice. SLICE_TYPE_TREE is the type of
// the slice. VALUES is the value pointer and COUNT is the number of
// entries. If CAPACITY is not NULL, it is the capacity; otherwise
diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc
index ac9510ed9a6..c6ff9886090 100644
--- a/gcc/go/gofrontend/gogo.cc
+++ b/gcc/go/gofrontend/gogo.cc
@@ -575,6 +575,164 @@ Gogo::current_bindings() const
return this->globals_;
}
+// Add statements to INIT_STMTS which run the initialization
+// functions for imported packages. This is only used for the "main"
+// package.
+
+void
+Gogo::init_imports(std::vector<Bstatement*>& init_stmts)
+{
+ go_assert(this->is_main_package());
+
+ if (this->imported_init_fns_.empty())
+ return;
+
+ Location unknown_loc = Linemap::unknown_location();
+ Function_type* func_type =
+ Type::make_function_type(NULL, NULL, NULL, unknown_loc);
+ Btype* fntype = func_type->get_backend_fntype(this);
+
+ // We must call them in increasing priority order.
+ std::vector<Import_init> v;
+ for (std::set<Import_init>::const_iterator p =
+ this->imported_init_fns_.begin();
+ p != this->imported_init_fns_.end();
+ ++p)
+ v.push_back(*p);
+ std::sort(v.begin(), v.end());
+
+ // We build calls to the init functions, which take no arguments.
+ std::vector<Bexpression*> empty_args;
+ for (std::vector<Import_init>::const_iterator p = v.begin();
+ p != v.end();
+ ++p)
+ {
+ std::string user_name = p->package_name() + ".init";
+ const std::string& init_name(p->init_name());
+
+ Bfunction* pfunc = this->backend()->function(fntype, user_name, init_name,
+ true, true, true, false,
+ false, unknown_loc);
+ Bexpression* pfunc_code =
+ this->backend()->function_code_expression(pfunc, unknown_loc);
+ Bexpression* pfunc_call =
+ this->backend()->call_expression(pfunc_code, empty_args, unknown_loc);
+ init_stmts.push_back(this->backend()->expression_statement(pfunc_call));
+ }
+}
+
+// Register global variables with the garbage collector. We need to
+// register all variables which can hold a pointer value. They become
+// roots during the mark phase. We build a struct that is easy to
+// hook into a list of roots.
+
+// struct __go_gc_root_list
+// {
+// struct __go_gc_root_list* __next;
+// struct __go_gc_root
+// {
+// void* __decl;
+// size_t __size;
+// } __roots[];
+// };
+
+// The last entry in the roots array has a NULL decl field.
+
+void
+Gogo::register_gc_vars(const std::vector<Named_object*>& var_gc,
+ std::vector<Bstatement*>& init_stmts)
+{
+ if (var_gc.empty())
+ return;
+
+ Type* pvt = Type::make_pointer_type(Type::make_void_type());
+ Type* uint_type = Type::lookup_integer_type("uint");
+ Struct_type* root_type = Type::make_builtin_struct_type(2,
+ "__decl", pvt,
+ "__size", uint_type);
+
+ Location builtin_loc = Linemap::predeclared_location();
+ size_t count = var_gc.size();
+ mpz_t lenval;
+ mpz_init_set_ui(lenval, count);
+ Expression* length = Expression::make_integer(&lenval, NULL, builtin_loc);
+ mpz_clear(lenval);
+
+ Array_type* root_array_type = Type::make_array_type(root_type, length);
+ Type* ptdt = Type::make_type_descriptor_ptr_type();
+ Struct_type* root_list_type =
+ Type::make_builtin_struct_type(2,
+ "__next", ptdt,
+ "__roots", root_array_type);
+
+ // Build an initializer for the __roots array.
+
+ Expression_list* roots_init = new Expression_list();
+
+ size_t i = 0;
+ for (std::vector<Named_object*>::const_iterator p = var_gc.begin();
+ p != var_gc.end();
+ ++p, ++i)
+ {
+ Expression_list* init = new Expression_list();
+
+ Location no_loc = (*p)->location();
+ Expression* decl = Expression::make_var_reference(*p, no_loc);
+ Expression* decl_addr =
+ Expression::make_unary(OPERATOR_AND, decl, no_loc);
+ init->push_back(decl_addr);
+
+ Expression* decl_size =
+ Expression::make_type_info(decl->type(), Expression::TYPE_INFO_SIZE);
+ init->push_back(decl_size);
+
+ Expression* root_ctor =
+ Expression::make_struct_composite_literal(root_type, init, no_loc);
+ roots_init->push_back(root_ctor);
+ }
+
+ // The list ends with a NULL entry.
+
+ Expression_list* null_init = new Expression_list();
+ Expression* nil = Expression::make_nil(builtin_loc);
+ null_init->push_back(nil);
+
+ mpz_t zval;
+ mpz_init_set_ui(zval, 0UL);
+ Expression* zero = Expression::make_integer(&zval, NULL, builtin_loc);
+ mpz_clear(zval);
+ null_init->push_back(zero);
+
+ Expression* null_root_ctor =
+ Expression::make_struct_composite_literal(root_type, null_init,
+ builtin_loc);
+ roots_init->push_back(null_root_ctor);
+
+ // Build a constructor for the struct.
+
+ Expression_list* root_list_init = new Expression_list();
+ root_list_init->push_back(nil);
+
+ Expression* roots_ctor =
+ Expression::make_array_composite_literal(root_array_type, roots_init,
+ builtin_loc);
+ root_list_init->push_back(roots_ctor);
+
+ Expression* root_list_ctor =
+ Expression::make_struct_composite_literal(root_list_type, root_list_init,
+ builtin_loc);
+
+ Expression* root_addr = Expression::make_unary(OPERATOR_AND, root_list_ctor,
+ builtin_loc);
+ root_addr->unary_expression()->set_is_gc_root();
+ Expression* register_roots = Runtime::make_call(Runtime::REGISTER_GC_ROOTS,
+ builtin_loc, 1, root_addr);
+
+ Translate_context context(this, NULL, NULL, NULL);
+ Bexpression* bcall = tree_to_expr(register_roots->get_tree(&context));
+ init_stmts.push_back(this->backend()->expression_statement(bcall));
+}
+
// Get the name to use for the import control function. If there is a
// global function or variable, then we know that that name must be
// unique in the link, and we use it as the basis for our name.
@@ -614,6 +772,521 @@ Gogo::initialization_function_decl()
return Named_object::make_function(name, NULL, initfn);
}
+// Create the magic initialization function. CODE_STMT is the
+// code that it needs to run.
+
+Named_object*
+Gogo::create_initialization_function(Named_object* initfn,
+ Bstatement* code_stmt)
+{
+ // Make sure that we thought we needed an initialization function,
+ // as otherwise we will not have reported it in the export data.
+ go_assert(this->is_main_package() || this->need_init_fn_);
+
+ if (initfn == NULL)
+ initfn = this->initialization_function_decl();
+
+ // Bind the initialization function code to a block.
+ Bfunction* fndecl = initfn->func_value()->get_or_make_decl(this, initfn);
+ Location pkg_loc = this->package_->location();
+ std::vector<Bvariable*> vars;
+ this->backend()->block(fndecl, NULL, vars, pkg_loc, pkg_loc);
+
+ if (!this->backend()->function_set_body(fndecl, code_stmt))
+ {
+ go_assert(saw_errors());
+ return NULL;
+ }
+ return initfn;
+}
+
+// Search for references to VAR in any statements or called functions.
+
+class Find_var : public Traverse
+{
+ public:
+ // A hash table we use to avoid looping. The index is the name of a
+ // named object. We only look through objects defined in this
+ // package.
+ typedef Unordered_set(const void*) Seen_objects;
+
+ Find_var(Named_object* var, Seen_objects* seen_objects)
+ : Traverse(traverse_expressions),
+ var_(var), seen_objects_(seen_objects), found_(false)
+ { }
+
+ // Whether the variable was found.
+ bool
+ found() const
+ { return this->found_; }
+
+ int
+ expression(Expression**);
+
+ private:
+ // The variable we are looking for.
+ Named_object* var_;
+ // Names of objects we have already seen.
+ Seen_objects* seen_objects_;
+ // True if the variable was found.
+ bool found_;
+};
+
+// See if EXPR refers to VAR, looking through function calls and
+// variable initializations.
+
+int
+Find_var::expression(Expression** pexpr)
+{
+ Expression* e = *pexpr;
+
+ Var_expression* ve = e->var_expression();
+ if (ve != NULL)
+ {
+ Named_object* v = ve->named_object();
+ if (v == this->var_)
+ {
+ this->found_ = true;
+ return TRAVERSE_EXIT;
+ }
+
+ if (v->is_variable() && v->package() == NULL)
+ {
+ Expression* init = v->var_value()->init();
+ if (init != NULL)
+ {
+ std::pair<Seen_objects::iterator, bool> ins =
+ this->seen_objects_->insert(v);
+ if (ins.second)
+ {
+ // This is the first time we have seen this name.
+ if (Expression::traverse(&init, this) == TRAVERSE_EXIT)
+ return TRAVERSE_EXIT;
+ }
+ }
+ }
+ }
+
+ // We traverse the code of any function we see. Note that this
+ // means that we will traverse the code of a function whose address
+ // is taken even if it is not called.
+ Func_expression* fe = e->func_expression();
+ if (fe != NULL)
+ {
+ const Named_object* f = fe->named_object();
+ if (f->is_function() && f->package() == NULL)
+ {
+ std::pair<Seen_objects::iterator, bool> ins =
+ this->seen_objects_->insert(f);
+ if (ins.second)
+ {
+ // This is the first time we have seen this name.
+ if (f->func_value()->block()->traverse(this) == TRAVERSE_EXIT)
+ return TRAVERSE_EXIT;
+ }
+ }
+ }
+
+ Temporary_reference_expression* tre = e->temporary_reference_expression();
+ if (tre != NULL)
+ {
+ Temporary_statement* ts = tre->statement();
+ Expression* init = ts->init();
+ if (init != NULL)
+ {
+ std::pair<Seen_objects::iterator, bool> ins =
+ this->seen_objects_->insert(ts);
+ if (ins.second)
+ {
+ // This is the first time we have seen this temporary
+ // statement.
+ if (Expression::traverse(&init, this) == TRAVERSE_EXIT)
+ return TRAVERSE_EXIT;
+ }
+ }
+ }
+
+ return TRAVERSE_CONTINUE;
+}
+
+// Return true if EXPR, PREINIT, or DEP refers to VAR.
+
+static bool
+expression_requires(Expression* expr, Block* preinit, Named_object* dep,
+ Named_object* var)
+{
+ Find_var::Seen_objects seen_objects;
+ Find_var find_var(var, &seen_objects);
+ if (expr != NULL)
+ Expression::traverse(&expr, &find_var);
+ if (preinit != NULL)
+ preinit->traverse(&find_var);
+ if (dep != NULL)
+ {
+ Expression* init = dep->var_value()->init();
+ if (init != NULL)
+ Expression::traverse(&init, &find_var);
+ if (dep->var_value()->has_pre_init())
+ dep->var_value()->preinit()->traverse(&find_var);
+ }
+
+ return find_var.found();
+}
+
+// Sort variable initializations. If the initialization expression
+// for variable A refers directly or indirectly to the initialization
+// expression for variable B, then we must initialize B before A.
+
+class Var_init
+{
+ public:
+ Var_init()
+ : var_(NULL), init_(NULL)
+ { }
+
+ Var_init(Named_object* var, Bstatement* init)
+ : var_(var), init_(init)
+ { }
+
+ // Return the variable.
+ Named_object*
+ var() const
+ { return this->var_; }
+
+ // Return the initialization expression.
+ Bstatement*
+ init() const
+ { return this->init_; }
+
+ private:
+ // The variable being initialized.
+ Named_object* var_;
+ // The initialization statement.
+ Bstatement* init_;
+};
+
+typedef std::list<Var_init> Var_inits;
+
+// Sort the variable initializations. The rule we follow is that we
+// emit them in the order they appear in the array, except that if the
+// initialization expression for a variable V1 depends upon another
+// variable V2 then we initialize V1 after V2.
+
+static void
+sort_var_inits(Gogo* gogo, Var_inits* var_inits)
+{
+ typedef std::pair<Named_object*, Named_object*> No_no;
+ typedef std::map<No_no, bool> Cache;
+ Cache cache;
+
+ Var_inits ready;
+ while (!var_inits->empty())
+ {
+ Var_inits::iterator p1 = var_inits->begin();
+ Named_object* var = p1->var();
+ Expression* init = var->var_value()->init();
+ Block* preinit = var->var_value()->preinit();
+ Named_object* dep = gogo->var_depends_on(var->var_value());
+
+ // Start walking through the list to see which variables VAR
+ // needs to wait for.
+ Var_inits::iterator p2 = p1;
+ ++p2;
+
+ for (; p2 != var_inits->end(); ++p2)
+ {
+ Named_object* p2var = p2->var();
+ No_no key(var, p2var);
+ std::pair<Cache::iterator, bool> ins =
+ cache.insert(std::make_pair(key, false));
+ if (ins.second)
+ ins.first->second = expression_requires(init, preinit, dep, p2var);
+ if (ins.first->second)
+ {
+ // Check for cycles.
+ key = std::make_pair(p2var, var);
+ ins = cache.insert(std::make_pair(key, false));
+ if (ins.second)
+ ins.first->second =
+ expression_requires(p2var->var_value()->init(),
+ p2var->var_value()->preinit(),
+ gogo->var_depends_on(p2var->var_value()),
+ var);
+ if (ins.first->second)
+ {
+ error_at(var->location(),
+ ("initialization expressions for %qs and "
+ "%qs depend upon each other"),
+ var->message_name().c_str(),
+ p2var->message_name().c_str());
+ inform(p2->var()->location(), "%qs defined here",
+ p2var->message_name().c_str());
+ p2 = var_inits->end();
+ }
+ else
+ {
+ // We can't emit P1 until P2 is emitted. Move P1.
+ Var_inits::iterator p3 = p2;
+ ++p3;
+ var_inits->splice(p3, *var_inits, p1);
+ }
+ break;
+ }
+ }
+
+ if (p2 == var_inits->end())
+ {
+ // VAR does not depends upon any other initialization expressions.
+
+ // Check for a loop of VAR on itself. We only do this if
+ // INIT is not NULL and there is no dependency; when INIT is
+ // NULL, it means that PREINIT sets VAR, which we will
+ // interpret as a loop.
+ if (init != NULL && dep == NULL
+ && expression_requires(init, preinit, NULL, var))
+ error_at(var->location(),
+ "initialization expression for %qs depends upon itself",
+ var->message_name().c_str());
+ ready.splice(ready.end(), *var_inits, p1);
+ }
+ }
+
+ // Now READY is the list in the desired initialization order.
+ var_inits->swap(ready);
+}
+
+// Write out the global definitions.
+
+void
+Gogo::write_globals()
+{
+ this->build_interface_method_tables();
+
+ Bindings* bindings = this->current_bindings();
+
+ for (Bindings::const_declarations_iterator p = bindings->begin_declarations();
+ p != bindings->end_declarations();
+ ++p)
+ {
+ // If any function declarations needed a descriptor, make sure
+ // we build it.
+ Named_object* no = p->second;
+ if (no->is_function_declaration())
+ no->func_declaration_value()->build_backend_descriptor(this);
+ }
+
+ // Lists of globally declared types, variables, constants, and functions
+ // that must be defined.
+ std::vector<Btype*> type_decls;
+ std::vector<Bvariable*> var_decls;
+ std::vector<Bexpression*> const_decls;
+ std::vector<Bfunction*> func_decls;
+
+ // The init function declaration, if necessary.
+ Named_object* init_fndecl = NULL;
+
+ std::vector<Bstatement*> init_stmts;
+ std::vector<Bstatement*> var_init_stmts;
+
+ if (this->is_main_package())
+ this->init_imports(init_stmts);
+
+ // A list of variable initializations.
+ Var_inits var_inits;
+
+ // A list of variables which need to be registered with the garbage
+ // collector.
+ size_t count_definitions = bindings->size_definitions();
+ std::vector<Named_object*> var_gc;
+ var_gc.reserve(count_definitions);
+
+ for (Bindings::const_definitions_iterator p = bindings->begin_definitions();
+ p != bindings->end_definitions();
+ ++p)
+ {
+ Named_object* no = *p;
+ go_assert(!no->is_type_declaration() && !no->is_function_declaration());
+
+ // There is nothing to do for a package.
+ if (no->is_package())
+ continue;
+
+ // There is nothing to do for an object which was imported from
+ // a different package into the global scope.
+ if (no->package() != NULL)
+ continue;
+
+ // Skip blank named functions and constants.
+ if ((no->is_function() && no->func_value()->is_sink())
+ || (no->is_const() && no->const_value()->is_sink()))
+ continue;
+
+ // There is nothing useful we can output for constants which
+ // have ideal or non-integral type.
+ if (no->is_const())
+ {
+ Type* type = no->const_value()->type();
+ if (type == NULL)
+ type = no->const_value()->expr()->type();
+ if (type->is_abstract() || !type->is_numeric_type())
+ continue;
+ }
+
+ if (!no->is_variable())
+ no->get_backend(this, const_decls, type_decls, func_decls);
+ else
+ {
+ Variable* var = no->var_value();
+ Bvariable* bvar = no->get_backend_variable(this, NULL);
+ var_decls.push_back(bvar);
+
+ // Check for a sink variable, which may be used to run an
+ // initializer purely for its side effects.
+ bool is_sink = no->name()[0] == '_' && no->name()[1] == '.';
+
+ Bstatement* var_init_stmt = NULL;
+ if (!var->has_pre_init())
+ {
+ Bexpression* var_binit = var->get_init(this, NULL);
+
+ // If the backend representation of the variable initializer is
+ // constant, we can just set the initial value using
+ // global_var_set_init instead of during the init() function.
+ // The initializer is constant if it is the zero-value of the
+ // variable's type or if the initial value is an immutable value
+ // that is not copied to the heap.
+ bool is_constant_initializer = false;
+ if (var->init() == NULL)
+ is_constant_initializer = true;
+ else
+ {
+ Type* var_type = var->type();
+ Expression* init = var->init();
+ Expression* init_cast =
+ Expression::make_cast(var_type, init, var->location());
+ is_constant_initializer =
+ init_cast->is_immutable() && !var_type->has_pointer();
+ }
+
+ if (var_binit == NULL)
+ ;
+ else if (is_constant_initializer)
+ {
+ if (expression_requires(var->init(), NULL,
+ this->var_depends_on(var), no))
+ error_at(no->location(),
+ "initialization expression for %qs depends "
+ "upon itself",
+ no->message_name().c_str());
+ this->backend()->global_variable_set_init(bvar, var_binit);
+ }
+ else if (is_sink)
+ var_init_stmt =
+ this->backend()->expression_statement(var_binit);
+ else
+ {
+ Location loc = var->location();
+ Bexpression* var_expr =
+ this->backend()->var_expression(bvar, loc);
+ var_init_stmt =
+ this->backend()->assignment_statement(var_expr, var_binit,
+ loc);
+ }
+ }
+ else
+ {
+ // We are going to create temporary variables which
+ // means that we need an fndecl.
+ if (init_fndecl == NULL)
+ init_fndecl = this->initialization_function_decl();
+
+ Bvariable* var_decl = is_sink ? NULL : bvar;
+ var_init_stmt = var->get_init_block(this, init_fndecl, var_decl);
+ }
+
+ if (var_init_stmt != NULL)
+ {
+ if (var->init() == NULL && !var->has_pre_init())
+ var_init_stmts.push_back(var_init_stmt);
+ else
+ var_inits.push_back(Var_init(no, var_init_stmt));
+ }
+ else if (this->var_depends_on(var) != NULL)
+ {
+ // This variable is initialized from something that is
+ // not in its init or preinit. This variable needs to
+ // participate in dependency analysis sorting, in case
+ // some other variable depends on this one.
+ Btype* btype = no->var_value()->type()->get_backend(this);
+ Bexpression* zero = this->backend()->zero_expression(btype);
+ Bstatement* zero_stmt =
+ this->backend()->expression_statement(zero);
+ var_inits.push_back(Var_init(no, zero_stmt));
+ }
+
+ if (!is_sink && var->type()->has_pointer())
+ var_gc.push_back(no);
+ }
+ }
+
+ // Register global variables with the garbage collector.
+ this->register_gc_vars(var_gc, init_stmts);
+
+ // Simple variable initializations, after all variables are
+ // registered.
+ init_stmts.push_back(this->backend()->statement_list(var_init_stmts));
+
+ // Complete variable initializations, first sorting them into a
+ // workable order.
+ if (!var_inits.empty())
+ {
+ sort_var_inits(this, &var_inits);
+ for (Var_inits::const_iterator p = var_inits.begin();
+ p != var_inits.end();
+ ++p)
+ init_stmts.push_back(p->init());
+ }
+
+ // After all the variables are initialized, call the init
+ // functions if there are any. Init functions take no arguments, so
+ // we pass in EMPTY_ARGS to call them.
+ std::vector<Bexpression*> empty_args;
+ for (std::vector<Named_object*>::const_iterator p =
+ this->init_functions_.begin();
+ p != this->init_functions_.end();
+ ++p)
+ {
+ Location func_loc = (*p)->location();
+ Function* func = (*p)->func_value();
+ Bfunction* initfn = func->get_or_make_decl(this, *p);
+ Bexpression* func_code =
+ this->backend()->function_code_expression(initfn, func_loc);
+ Bexpression* call = this->backend()->call_expression(func_code,
+ empty_args,
+ func_loc);
+ init_stmts.push_back(this->backend()->expression_statement(call));
+ }
+
+ // Set up a magic function to do all the initialization actions.
+ // This will be called if this package is imported.
+ Bstatement* init_fncode = this->backend()->statement_list(init_stmts);
+ if (this->need_init_fn_ || this->is_main_package())
+ {
+ init_fndecl =
+ this->create_initialization_function(init_fndecl, init_fncode);
+ if (init_fndecl != NULL)
+ func_decls.push_back(init_fndecl->func_value()->get_decl());
+ }
+
+ // We should not have seen any new bindings created during the conversion.
+ go_assert(count_definitions == this->current_bindings()->size_definitions());
+
+ // Define all globally declared values.
+ if (!saw_errors())
+ this->backend()->write_global_definitions(type_decls, const_decls,
+ func_decls, var_decls);
+}
+
// Return the current block.
Block*
@@ -4182,6 +4855,15 @@ Function::get_or_make_decl(Gogo* gogo, Named_object* no)
return this->fndecl_;
}
+// Return the function's decl after it has been built.
+
+Bfunction*
+Function::get_decl() const
+{
+ go_assert(this->fndecl_ != NULL);
+ return this->fndecl_;
+}
+
// Build the backend representation for the function code.
void
@@ -5266,8 +5948,7 @@ Variable::get_init_block(Gogo* gogo, Named_object* function,
{
Location loc = this->location();
Expression* val_expr =
- Expression::convert_for_assignment(gogo, this->type(),
- this->init_, this->location());
+ Expression::make_cast(this->type(), this->init_, loc);
Bexpression* val = tree_to_expr(val_expr->get_tree(&context));
Bexpression* var_ref = gogo->backend()->var_expression(var_decl, loc);
decl_init = gogo->backend()->assignment_statement(var_ref, val, loc);
@@ -5353,8 +6034,7 @@ Variable::get_backend_variable(Gogo* gogo, Named_object* function,
}
else
{
- tree fndecl = function->func_value()->get_decl();
- Bfunction* bfunction = tree_to_function(fndecl);
+ Bfunction* bfunction = function->func_value()->get_decl();
bool is_address_taken = (this->is_non_escaping_address_taken_
&& !this->is_in_heap());
if (is_parameter)
@@ -5391,8 +6071,7 @@ Result_variable::get_backend_variable(Gogo* gogo, Named_object* function,
if (this->is_in_heap())
type = Type::make_pointer_type(type);
Btype* btype = type->get_backend(gogo);
- tree fndecl = function->func_value()->get_decl();
- Bfunction* bfunction = tree_to_function(fndecl);
+ Bfunction* bfunction = function->func_value()->get_decl();
std::string n = Gogo::unpack_hidden_name(name);
bool is_address_taken = (this->is_non_escaping_address_taken_
&& !this->is_in_heap());
@@ -5482,6 +6161,33 @@ Named_constant::import_const(Import* imp, std::string* pname, Type** ptype,
imp->require_c_string(";\n");
}
+// Get the backend representation.
+
+Bexpression*
+Named_constant::get_backend(Gogo* gogo, Named_object* const_no)
+{
+ if (this->bconst_ == NULL)
+ {
+ Translate_context subcontext(gogo, NULL, NULL, NULL);
+ Type* type = this->type();
+ Location loc = this->location();
+
+ Expression* const_ref = Expression::make_const_reference(const_no, loc);
+ Bexpression* const_decl =
+ tree_to_expr(const_ref->get_tree(&subcontext));
+ if (type != NULL && type->is_numeric_type())
+ {
+ Btype* btype = type->get_backend(gogo);
+ std::string name = const_no->get_id(gogo);
+ const_decl =
+ gogo->backend()->named_constant_expression(btype, name,
+ const_decl, loc);
+ }
+ this->bconst_ = const_decl;
+ }
+ return this->bconst_;
+}
+
// Add a method.
Named_object*
@@ -5552,8 +6258,7 @@ Unknown_name::set_real_named_object(Named_object* no)
Named_object::Named_object(const std::string& name,
const Package* package,
Classification classification)
- : name_(name), package_(package), classification_(classification),
- tree_(NULL)
+ : name_(name), package_(package), classification_(classification)
{
if (Gogo::is_sink_name(name))
go_assert(classification == NAMED_OBJECT_SINK);
@@ -5928,6 +6633,72 @@ Named_object::get_id(Gogo* gogo)
return decl_name;
}
+// Get the backend representation for this named object.
+
+void
+Named_object::get_backend(Gogo* gogo, std::vector<Bexpression*>& const_decls,
+ std::vector<Btype*>& type_decls,
+ std::vector<Bfunction*>& func_decls)
+{
+ switch (this->classification_)
+ {
+ case NAMED_OBJECT_CONST:
+ if (!Gogo::is_erroneous_name(this->name_))
+ const_decls.push_back(this->u_.const_value->get_backend(gogo, this));
+ break;
+
+ case NAMED_OBJECT_TYPE:
+ {
+ Named_type* named_type = this->u_.type_value;
+ if (!Gogo::is_erroneous_name(this->name_))
+ type_decls.push_back(named_type->get_backend(gogo));
+
+ // We need to produce a type descriptor for every named
+ // type, and for a pointer to every named type, since
+ // other files or packages might refer to them. We need
+ // to do this even for hidden types, because they might
+ // still be returned by some function. Simply calling the
+ // type_descriptor method is enough to create the type
+ // descriptor, even though we don't do anything with it.
+ if (this->package_ == NULL)
+ {
+ named_type->
+ type_descriptor_pointer(gogo, Linemap::predeclared_location());
+ Type* pn = Type::make_pointer_type(named_type);
+ pn->type_descriptor_pointer(gogo, Linemap::predeclared_location());
+ }
+ }
+ break;
+
+ case NAMED_OBJECT_TYPE_DECLARATION:
+ error("reference to undefined type %qs",
+ this->message_name().c_str());
+ return;
+
+ case NAMED_OBJECT_VAR:
+ case NAMED_OBJECT_RESULT_VAR:
+ case NAMED_OBJECT_SINK:
+ go_unreachable();
+
+ case NAMED_OBJECT_FUNC:
+ {
+ Function* func = this->u_.func_value;
+ if (!Gogo::is_erroneous_name(this->name_))
+ func_decls.push_back(func->get_or_make_decl(gogo, this));
+
+ if (func->block() != NULL)
+ func->build(gogo, this);
+ }
+ break;
+
+ case NAMED_OBJECT_ERRONEOUS:
+ break;
+
+ default:
+ go_unreachable();
+ }
+}
+
// Class Bindings.
Bindings::Bindings(Bindings* enclosing)
@@ -6400,8 +7171,7 @@ Label::get_backend_label(Translate_context* context)
if (this->blabel_ == NULL)
{
Function* function = context->function()->func_value();
- tree fndecl = function->get_decl();
- Bfunction* bfunction = tree_to_function(fndecl);
+ Bfunction* bfunction = function->get_decl();
this->blabel_ = context->backend()->label(bfunction, this->name_,
this->location_);
}
@@ -6427,8 +7197,7 @@ Unnamed_label::get_blabel(Translate_context* context)
if (this->blabel_ == NULL)
{
Function* function = context->function()->func_value();
- tree fndecl = function->get_decl();
- Bfunction* bfunction = tree_to_function(fndecl);
+ Bfunction* bfunction = function->get_decl();
this->blabel_ = context->backend()->label(bfunction, "",
this->location_);
}
diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h
index dd43d269f40..0be81b2aafe 100644
--- a/gcc/go/gofrontend/gogo.h
+++ b/gcc/go/gofrontend/gogo.h
@@ -44,6 +44,7 @@ class Backend;
class Export;
class Import;
class Bexpression;
+class Btype;
class Bstatement;
class Bblock;
class Bvariable;
@@ -591,11 +592,6 @@ class Gogo
Expression*
runtime_error(int code, Location);
- // Build a builtin struct with a list of fields.
- static tree
- builtin_struct(tree* ptype, const char* struct_name, tree struct_type,
- int nfields, ...);
-
// Mark a function declaration as a builtin library function.
static void
mark_fndecl_as_builtin_library(tree fndecl);
@@ -650,17 +646,18 @@ class Gogo
Named_object*
initialization_function_decl();
- // Write the magic initialization function.
- void
- write_initialization_function(Named_object* fndecl, tree init_stmt_list);
+ // Create the magic initialization function.
+ Named_object*
+ create_initialization_function(Named_object* fndecl, Bstatement* code_stmt);
// Initialize imported packages.
void
- init_imports(tree*);
+ init_imports(std::vector<Bstatement*>&);
// Register variables with the garbage collector.
void
- register_gc_vars(const std::vector<Named_object*>&, tree*);
+ register_gc_vars(const std::vector<Named_object*>&,
+ std::vector<Bstatement*>&);
// Type used to map import names to packages.
typedef std::map<std::string, Package*> Imports;
@@ -1086,7 +1083,7 @@ class Function
get_or_make_decl(Gogo*, Named_object*);
// Return the function's decl after it has been built.
- tree
+ Bfunction*
get_decl() const;
// Set the function decl to hold a backend representation of the function
@@ -1675,7 +1672,7 @@ class Named_constant
Named_constant(Type* type, Expression* expr, int iota_value,
Location location)
: type_(type), expr_(expr), iota_value_(iota_value), location_(location),
- lowering_(false), is_sink_(false)
+ lowering_(false), is_sink_(false), bconst_(NULL)
{ }
Type*
@@ -1737,6 +1734,10 @@ class Named_constant
static void
import_const(Import*, std::string*, Type**, Expression**);
+ // Get the backend representation of the constant value.
+ Bexpression*
+ get_backend(Gogo*, Named_object*);
+
private:
// The type of the constant.
Type* type_;
@@ -1754,6 +1755,8 @@ class Named_constant
bool lowering_;
// Whether this constant is blank named and needs only type checking.
bool is_sink_;
+ // The backend representation of the constant value.
+ Bexpression* bconst_;
};
// A type declaration.
@@ -2176,9 +2179,10 @@ class Named_object
std::string
get_id(Gogo*);
- // Return a tree representing this object.
- tree
- get_tree(Gogo*, Named_object* function);
+ // Get the backend representation of this object.
+ void
+ get_backend(Gogo*, std::vector<Bexpression*>&, std::vector<Btype*>&,
+ std::vector<Bfunction*>&);
// Define a type declaration.
void
@@ -2219,8 +2223,6 @@ class Named_object
Function_declaration* func_declaration_value;
Package* package_value;
} u_;
- // The DECL tree for this object if we have already converted it.
- tree tree_;
};
// A binding contour. This binds names to objects.
diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc
index 49a864faa44..dabf1a83af6 100644
--- a/gcc/go/gofrontend/statements.cc
+++ b/gcc/go/gofrontend/statements.cc
@@ -434,15 +434,9 @@ Temporary_statement::do_get_backend(Translate_context* context)
{
go_assert(this->bvariable_ == NULL);
- // FIXME: Permitting FUNCTION to be NULL here is a temporary measure
- // until we have a better representation of the init function.
Named_object* function = context->function();
- Bfunction* bfunction;
- if (function == NULL)
- bfunction = NULL;
- else
- bfunction = tree_to_function(function->func_value()->get_decl());
-
+ go_assert(function != NULL);
+ Bfunction* bfunction = function->func_value()->get_decl();
Btype* btype = this->type()->get_backend(context->gogo());
Bexpression* binit;
@@ -2781,8 +2775,6 @@ Return_statement::do_get_backend(Translate_context* context)
Location loc = this->location();
Function* function = context->function()->func_value();
- tree fndecl = function->get_decl();
-
Function::Results* results = function->result_variables();
std::vector<Bexpression*> retvals;
if (results != NULL && !results->empty())
@@ -2797,7 +2789,7 @@ Return_statement::do_get_backend(Translate_context* context)
}
}
- return context->backend()->return_statement(tree_to_function(fndecl),
+ return context->backend()->return_statement(function->get_decl(),
retvals, loc);
}
@@ -3803,8 +3795,10 @@ Constant_switch_statement::do_get_backend(Translate_context* context)
this->clauses_->get_backend(context, break_label, &all_cases,
&all_statements);
+ Bfunction* bfunction = context->function()->func_value()->get_decl();
Bstatement* switch_statement;
- switch_statement = context->backend()->switch_statement(switch_val_expr,
+ switch_statement = context->backend()->switch_statement(bfunction,
+ switch_val_expr,
all_cases,
all_statements,
this->location());
@@ -4980,7 +4974,9 @@ Select_clauses::get_backend(Translate_context* context,
std::vector<Bstatement*> statements;
statements.reserve(2);
- Bstatement* switch_stmt = context->backend()->switch_statement(bcall,
+ Bfunction* bfunction = context->function()->func_value()->get_decl();
+ Bstatement* switch_stmt = context->backend()->switch_statement(bfunction,
+ bcall,
cases,
clauses,
location);
diff --git a/gcc/graphite-scop-detection.c b/gcc/graphite-scop-detection.c
index 821f0846ef2..635e21a8519 100644
--- a/gcc/graphite-scop-detection.c
+++ b/gcc/graphite-scop-detection.c
@@ -474,8 +474,10 @@ scopdet_basic_block_info (basic_block bb, loop_p outermost_loop,
result.exits = false;
/* Mark bbs terminating a SESE region difficult, if they start
- a condition. */
- if (!single_succ_p (bb))
+ a condition or if the block it exits to cannot be split
+ with make_forwarder_block. */
+ if (!single_succ_p (bb)
+ || bb_has_abnormal_pred (single_succ (bb)))
result.difficult = true;
else
result.exit = single_succ (bb);
diff --git a/gcc/haifa-sched.c b/gcc/haifa-sched.c
index 2d66e5cab6a..5d16b4d0f94 100644
--- a/gcc/haifa-sched.c
+++ b/gcc/haifa-sched.c
@@ -1299,7 +1299,7 @@ recompute_todo_spec (rtx next, bool for_backtrack)
{
HARD_REG_SET t;
- find_all_hard_reg_sets (prev, &t);
+ find_all_hard_reg_sets (prev, &t, true);
if (TEST_HARD_REG_BIT (t, regno))
return HARD_DEP;
if (prev == pro)
@@ -3082,7 +3082,7 @@ check_clobbered_conditions (rtx insn)
if ((current_sched_info->flags & DO_PREDICATION) == 0)
return;
- find_all_hard_reg_sets (insn, &t);
+ find_all_hard_reg_sets (insn, &t, true);
restart:
for (i = 0; i < ready.n_ready; i++)
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 5411e00a3c4..a0f024a76ef 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -1730,6 +1730,9 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
&& OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
scan_array_reductions = true;
+ else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
+ && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
+ scan_array_reductions = true;
break;
case OMP_CLAUSE_SHARED:
@@ -1816,6 +1819,9 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
&& OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
+ else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
+ && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
+ scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
}
/* Create a new name for omp child function. Returns an identifier. */
@@ -3801,6 +3807,14 @@ lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
}
+ else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
+ && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
+ {
+ lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
+ gimple_seq_add_seq (stmt_list,
+ OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
+ OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
+ }
x = build_outer_var_ref (var, ctx);
if (is_reference (var))
diff --git a/gcc/passes.c b/gcc/passes.c
index 2be7856f29b..c0a76d62d21 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -132,7 +132,7 @@ opt_pass::opt_pass (const pass_data &data, context *ctxt)
void
pass_manager::execute_early_local_passes ()
{
- execute_pass_list (pass_early_local_passes_1->sub);
+ execute_pass_list (cfun, pass_early_local_passes_1->sub);
}
unsigned int
@@ -1498,27 +1498,17 @@ pass_manager::pass_manager (context *ctxt)
call CALLBACK on the current function. */
static void
-do_per_function (void (*callback) (void *data), void *data)
+do_per_function (void (*callback) (function *, void *data), void *data)
{
if (current_function_decl)
- callback (data);
+ callback (cfun, data);
else
{
struct cgraph_node *node;
FOR_EACH_DEFINED_FUNCTION (node)
if (node->analyzed && gimple_has_body_p (node->decl)
&& (!node->clone_of || node->decl != node->clone_of->decl))
- {
- push_cfun (DECL_STRUCT_FUNCTION (node->decl));
- callback (data);
- if (!flag_wpa)
- {
- free_dominance_info (CDI_DOMINATORS);
- free_dominance_info (CDI_POST_DOMINATORS);
- }
- pop_cfun ();
- ggc_collect ();
- }
+ callback (DECL_STRUCT_FUNCTION (node->decl), data);
}
}
@@ -1533,12 +1523,12 @@ static GTY ((length ("nnodes"))) cgraph_node_ptr *order;
call CALLBACK on the current function.
This function is global so that plugins can use it. */
void
-do_per_function_toporder (void (*callback) (void *data), void *data)
+do_per_function_toporder (void (*callback) (function *, void *data), void *data)
{
int i;
if (current_function_decl)
- callback (data);
+ callback (cfun, data);
else
{
gcc_assert (!order);
@@ -1554,15 +1544,7 @@ do_per_function_toporder (void (*callback) (void *data), void *data)
order[i] = NULL;
node->process = 0;
if (cgraph_function_with_gimple_body_p (node))
- {
- cgraph_get_body (node);
- push_cfun (DECL_STRUCT_FUNCTION (node->decl));
- callback (data);
- free_dominance_info (CDI_DOMINATORS);
- free_dominance_info (CDI_POST_DOMINATORS);
- pop_cfun ();
- ggc_collect ();
- }
+ callback (DECL_STRUCT_FUNCTION (node->decl), data);
}
}
ggc_free (order);
@@ -1573,14 +1555,16 @@ do_per_function_toporder (void (*callback) (void *data), void *data)
/* Helper function to perform function body dump. */
static void
-execute_function_dump (void *data)
+execute_function_dump (function *fn, void *data)
{
opt_pass *pass = (opt_pass *)data;
- if (dump_file && current_function_decl)
+ if (dump_file)
{
- if (cfun->curr_properties & PROP_trees)
- dump_function_to_file (current_function_decl, dump_file, dump_flags);
+ push_cfun (fn);
+
+ if (fn->curr_properties & PROP_trees)
+ dump_function_to_file (fn->decl, dump_file, dump_flags);
else
print_rtl_with_bb (dump_file, get_insns (), dump_flags);
@@ -1588,7 +1572,7 @@ execute_function_dump (void *data)
close the file before aborting. */
fflush (dump_file);
- if ((cfun->curr_properties & PROP_cfg)
+ if ((fn->curr_properties & PROP_cfg)
&& (dump_flags & TDF_GRAPH))
{
if (!pass->graph_dump_initialized)
@@ -1596,8 +1580,10 @@ execute_function_dump (void *data)
clean_graph_dump_file (dump_file_name);
pass->graph_dump_initialized = true;
}
- print_graph_cfg (dump_file_name, cfun);
+ print_graph_cfg (dump_file_name, fn);
}
+
+ pop_cfun ();
}
}
@@ -1728,13 +1714,15 @@ pass_manager::dump_profile_report () const
/* Perform all TODO actions that ought to be done on each function. */
static void
-execute_function_todo (void *data)
+execute_function_todo (function *fn, void *data)
{
unsigned int flags = (size_t)data;
- flags &= ~cfun->last_verified;
+ flags &= ~fn->last_verified;
if (!flags)
return;
+ push_cfun (fn);
+
/* Always cleanup the CFG before trying to update SSA. */
if (flags & TODO_cleanup_cfg)
{
@@ -1774,7 +1762,10 @@ execute_function_todo (void *data)
/* If we've seen errors do not bother running any verifiers. */
if (seen_error ())
- return;
+ {
+ pop_cfun ();
+ return;
+ }
#if defined ENABLE_CHECKING
if (flags & TODO_verify_ssa
@@ -1793,7 +1784,9 @@ execute_function_todo (void *data)
verify_rtl_sharing ();
#endif
- cfun->last_verified = flags & TODO_verify_all;
+ fn->last_verified = flags & TODO_verify_all;
+
+ pop_cfun ();
}
/* Perform all TODO actions. */
@@ -1855,9 +1848,9 @@ verify_interpass_invariants (void)
/* Clear the last verified flag. */
static void
-clear_last_verified (void *data ATTRIBUTE_UNUSED)
+clear_last_verified (function *fn, void *data ATTRIBUTE_UNUSED)
{
- cfun->last_verified = 0;
+ fn->last_verified = 0;
}
/* Helper function. Verify that the properties has been turn into the
@@ -1865,10 +1858,10 @@ clear_last_verified (void *data ATTRIBUTE_UNUSED)
#ifdef ENABLE_CHECKING
static void
-verify_curr_properties (void *data)
+verify_curr_properties (function *fn, void *data)
{
unsigned int props = (size_t)data;
- gcc_assert ((cfun->curr_properties & props) == props);
+ gcc_assert ((fn->curr_properties & props) == props);
}
#endif
@@ -1927,11 +1920,11 @@ pass_fini_dump_file (opt_pass *pass)
properties. */
static void
-update_properties_after_pass (void *data)
+update_properties_after_pass (function *fn, void *data)
{
opt_pass *pass = (opt_pass *) data;
- cfun->curr_properties = (cfun->curr_properties | pass->properties_provided)
- & ~pass->properties_destroyed;
+ fn->curr_properties = (fn->curr_properties | pass->properties_provided)
+ & ~pass->properties_destroyed;
}
/* Execute summary generation for all of the passes in IPA_PASS. */
@@ -2039,20 +2032,6 @@ execute_all_ipa_transforms (void)
}
}
-/* Callback for do_per_function to apply all IPA transforms. */
-
-static void
-apply_ipa_transforms (void *data)
-{
- struct cgraph_node *node = cgraph_get_node (current_function_decl);
- if (!node->global.inlined_to && node->ipa_transforms_to_apply.exists ())
- {
- *(bool *)data = true;
- execute_all_ipa_transforms ();
- rebuild_cgraph_edges ();
- }
-}
-
/* Check if PASS is explicitly disabled or enabled and return
the gate status. FUNC is the function to be processed, and
GATE_STATUS is the gate status determined by pass manager by
@@ -2124,8 +2103,26 @@ execute_one_pass (opt_pass *pass)
Apply all trnasforms first. */
if (pass->type == SIMPLE_IPA_PASS)
{
+ struct cgraph_node *node;
bool applied = false;
- do_per_function (apply_ipa_transforms, (void *)&applied);
+ FOR_EACH_DEFINED_FUNCTION (node)
+ if (node->analyzed
+ && cgraph_function_with_gimple_body_p (node)
+ && (!node->clone_of || node->decl != node->clone_of->decl))
+ {
+ if (!node->global.inlined_to
+ && node->ipa_transforms_to_apply.exists ())
+ {
+ cgraph_get_body (node);
+ push_cfun (DECL_STRUCT_FUNCTION (node->decl));
+ execute_all_ipa_transforms ();
+ rebuild_cgraph_edges ();
+ free_dominance_info (CDI_DOMINATORS);
+ free_dominance_info (CDI_POST_DOMINATORS);
+ pop_cfun ();
+ applied = true;
+ }
+ }
if (applied)
symtab_remove_unreachable_nodes (true, dump_file);
/* Restore current_pass. */
@@ -2202,20 +2199,33 @@ execute_one_pass (opt_pass *pass)
return true;
}
-void
-execute_pass_list (opt_pass *pass)
+static void
+execute_pass_list_1 (opt_pass *pass)
{
do
{
gcc_assert (pass->type == GIMPLE_PASS
|| pass->type == RTL_PASS);
if (execute_one_pass (pass) && pass->sub)
- execute_pass_list (pass->sub);
+ execute_pass_list_1 (pass->sub);
pass = pass->next;
}
while (pass);
}
+void
+execute_pass_list (function *fn, opt_pass *pass)
+{
+ push_cfun (fn);
+ execute_pass_list_1 (pass);
+ if (fn->cfg)
+ {
+ free_dominance_info (CDI_DOMINATORS);
+ free_dominance_info (CDI_POST_DOMINATORS);
+ }
+ pop_cfun ();
+}
+
/* Write out all LTO data. */
static void
write_lto (void)
@@ -2539,7 +2549,8 @@ execute_ipa_pass_list (opt_pass *pass)
if (pass->sub->type == GIMPLE_PASS)
{
invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_START, NULL);
- do_per_function_toporder ((void (*)(void *))execute_pass_list,
+ do_per_function_toporder ((void (*)(function *, void *))
+ execute_pass_list,
pass->sub);
invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_END, NULL);
}
diff --git a/gcc/rtl.h b/gcc/rtl.h
index cccb884ae88..f62c334351d 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -2231,7 +2231,7 @@ extern const_rtx set_of (const_rtx, const_rtx);
extern void record_hard_reg_sets (rtx, const_rtx, void *);
extern void record_hard_reg_uses (rtx *, void *);
#ifdef HARD_CONST
-extern void find_all_hard_reg_sets (const_rtx, HARD_REG_SET *);
+extern void find_all_hard_reg_sets (const_rtx, HARD_REG_SET *, bool);
#endif
extern void note_stores (const_rtx, void (*) (rtx, const_rtx, void *), void *);
extern void note_uses (rtx *, void (*) (rtx *, void *), void *);
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index 98c652894fb..82cfc1bf70b 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -1046,14 +1046,20 @@ record_hard_reg_sets (rtx x, const_rtx pat ATTRIBUTE_UNUSED, void *data)
/* Examine INSN, and compute the set of hard registers written by it.
Store it in *PSET. Should only be called after reload. */
void
-find_all_hard_reg_sets (const_rtx insn, HARD_REG_SET *pset)
+find_all_hard_reg_sets (const_rtx insn, HARD_REG_SET *pset, bool implicit)
{
rtx link;
CLEAR_HARD_REG_SET (*pset);
note_stores (PATTERN (insn), record_hard_reg_sets, pset);
if (CALL_P (insn))
- IOR_HARD_REG_SET (*pset, call_used_reg_set);
+ {
+ if (implicit)
+ IOR_HARD_REG_SET (*pset, call_used_reg_set);
+
+ for (link = CALL_INSN_FUNCTION_USAGE (insn); link; link = XEXP (link, 1))
+ record_hard_reg_sets (XEXP (link, 0), NULL, pset);
+ }
for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
if (REG_NOTE_KIND (link) == REG_INC)
record_hard_reg_sets (XEXP (link, 0), NULL, pset);
diff --git a/gcc/system.h b/gcc/system.h
index 8b5089a28d7..b20b5cfde1d 100644
--- a/gcc/system.h
+++ b/gcc/system.h
@@ -1035,7 +1035,7 @@ helper_const_non_const_cast (const char *p)
#endif
#endif
-#ifdef ENABLE_VALGRIND_CHECKING
+#ifdef ENABLE_VALGRIND_ANNOTATIONS
# ifdef HAVE_VALGRIND_MEMCHECK_H
# include <valgrind/memcheck.h>
# elif defined HAVE_MEMCHECK_H
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 70a0f89d592..261bb98a3a4 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,10 +1,156 @@
-i2014-04-24 Alan Lawrence <alan.lawrence@arm.com>
+2014-04-28 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/tree-ssa/vrp91.c: New testcase.
+ * gcc.dg/Wstrict-overflow-14.c: XFAIL.
+ * gcc.dg/Wstrict-overflow-15.c: Likewise.
+ * gcc.dg/Wstrict-overflow-18.c: Remove XFAIL.
+
+2014-04-28 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/60979
+ * gcc.dg/graphite/pr60979.c: New testcase.
+
+2014-04-28 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR c/60983
+ * gcc.dg/pr60114.c: Use signed chars.
+
+2014-04-28 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/59120
+ * g++.dg/cpp0x/alias-decl-43.C: New.
+
+2014-03-27 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/59604
+ PR fortran/58003
+ * gfortran.dg/no_range_check_3.f90: New test.
+
+2014-04-26 Jerry DeLisle <jvdelisle@gcc.gnu>
+
+ PR libfortran/52539
+ * gfortran.dg/namelist_utf8.f90: New test.
+
+2014-04-26 Uros Bizjak <ubizjak@gmail.com>
+
+ * gcc.dg/tree-ssa/alias-30.c (dg-options): Dump only fre1 details.
+ * gcc.dg/vect/pr60505.c: Cleanup vect tree dump.
+ * g++.dg/ipa/devirt-27.C (dg-options): Remove -fdump-ipa-devirt.
+
+2014-04-25 Cary Coutant <ccoutant@google.com>
+
+ PR debug/60929
+ * g++.dg/debug/dwarf2/dwarf4-nested.C: New test case.
+ * g++.dg/debug/dwarf2/dwarf4-typedef.C: Add
+ -fdebug-types-section flag.
+
+2014-04-25 Jiong Wang <jiong.wang@arm.com>
+
+ * gcc.target/arm/tail-long-call.c: New test.
+
+2014-04-25 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ PR tree-optimization/60930
+ * gcc.dg/torture/pr60930.c: New test.
+
+2014-04-25 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/60960
+ * gcc.c-torture/execute/pr60960.c: New test.
+
+2014-04-25 Marek Polacek <polacek@redhat.com>
+
+ * gcc.dg/pr18079-2.c: Fix quoting in dg-warning.
+
+2014-04-25 Marek Polacek <polacek@redhat.com>
+
+ PR c/18079
+ * gcc.dg/pr18079.c: New test.
+ * gcc.dg/pr18079-2.c: New test.
+
+2014-04-25 Uros Bizjak <ubizjak@gmail.com>
+
+ * c-c++-common/gomp/pr60823-2.c: Require effective target
+ vect_simd_clones.
+
+2014-04-25 Marek Polacek <polacek@redhat.com>
+
+ PR c/60114
+ * gcc.dg/pr60114.c: New test.
+
+2014-04-25 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.c-torture/execute/20140425-1.c: New test.
+
+2014-04-25 Marek Polacek <polacek@redhat.com>
+
+ PR c/60156
+ * c-c++-common/pr60156.c: New test.
+
+2014-04-25 Richard Biener <rguenther@suse.de>
+
+ PR ipa/60912
+ * g++.dg/opt/pr60912.C: New testcase.
+
+2014-04-25 Richard Biener <rguenther@suse.de>
+
+ PR ipa/60911
+ * gcc.dg/lto/pr60911_0.c: New testcase.
+
+2014-04-24 Cong Hou <congh@google.com>
+
+ PR tree-optimization/60896
+ * g++.dg/vect/pr60896.cc: New test.
+
+2014-04-24 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * gcc.target/powerpc/pack01.c: New test to test the new pack and
+ unpack builtin functionss for 128-bit types.
+ * gcc.target/powerpc/pack02.c: Likewise.
+ * gcc.target/powerpc/pack03.c: Likewise.
+ * gcc.target/powerpc/extend-divide-1.c: New test to test extended
+ divide builtin functionss.
+ * gcc.target/powerpc/extend-divide-2.c: Likewise.
+ * gcc.target/powerpc/bcd-1.c: New test for the new BCD builtin
+ functions.
+ * gcc.target/powerpc/bcd-2.c: Likewise.
+ * gcc.target/powerpc/bcd-3.c: Likewise.
+ * gcc.target/powerpc/dfp-builtin-1.c: New test for the new DFP
+ builtin functionss.
+ * gcc.target/powerpc/dfp-builtin-2.c: Likewise.
+
+2014-04-24 Vishnu K S <Vishnu.k_s@atmel.com>
+
+ * gcc/testsuite/gcc.dg/tree-ssa/isolate-1.c: Skip test if
+ keeps_null_pointer_checks.
+ * gcc/testsuite/gcc.dg/tree-ssa/isolate-2.c: Ditto.
+ * gcc/testsuite/gcc.dg/tree-ssa/isolate-3.c: Ditto.
+ * gcc/testsuite/gcc.dg/tree-ssa/isolate-4.c: Ditto.
+ * gcc/testsuite/gcc.dg/tree-ssa/isolate-5.c: Ditto.
+
+2014-04-24 Jakub Jelinek <jakub@redhat.com>
+
+ * c-c++-common/gomp/atomic-16.c: Remove all dg-error directives.
+ Replace load with read and store with write.
+
+2014-04-24 Jeff Law <law@redhat.com>
+
+ PR target/60822
+ * gcc.c-torture/pr60822.c: New test.
+ * gcc.c-torture/pr60822.x: New test.
+
+2014-04-24 Dinar Temirbulatov <dtemirbulatov@gmail.com>
+
+ PR c++/57958
+ * testsuite/g++.dg/cpp0x/pr57958.C: New test.
+
+2014-04-24 Alan Lawrence <alan.lawrence@arm.com>
* lib/target-supports.exp (check_effective_target_vect_perm): Return
true for aarch64_be.
2014-04-24 Radovan Obradovic <robradovic@mips.com>
- Tom de Vries <tom@codesourcery.com>
+ Tom de Vries <tom@codesourcery.com>
* gcc.dg/fuse-caller-save.c: New test.
@@ -36,7 +182,7 @@ i2014-04-24 Alan Lawrence <alan.lawrence@arm.com>
2014-04-23 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
- * gcc.target/aarch64/rev16_1.c: New test.
+ * gcc.target/aarch64/rev16_1.c: New test.
2014-04-23 Richard Biener <rguenther@suse.de>
@@ -241,7 +387,7 @@ i2014-04-24 Alan Lawrence <alan.lawrence@arm.com>
PR tree-optimization/60836
* g++.dg/vect/pr60836.cc: New testcase.
-2014-04-17 Richard Biener <rguenther@suse.de>
+2014-04-17 Richard Biener <rguenther@suse.de>
PR tree-optimization/60841
* gcc.dg/vect/pr60841.c: New testcase.
@@ -1924,8 +2070,7 @@ i2014-04-24 Alan Lawrence <alan.lawrence@arm.com>
2014-02-19 Paul Pluzhnikov <ppluzhnikov@google.com>
- * gcc.dg/vect/no-vfa-vect-depend-2.c (main1): Fix buffer
- overflow.
+ * gcc.dg/vect/no-vfa-vect-depend-2.c (main1): Fix buffer overflow.
2014-02-19 Jakub Jelinek <jakub@redhat.com>
@@ -2234,8 +2379,7 @@ i2014-04-24 Alan Lawrence <alan.lawrence@arm.com>
2014-02-10 Jakub Jelinek <jakub@redhat.com>
- * gcc.dg/vect/pr59984.c: Require effective target
- vect_simd_clones.
+ * gcc.dg/vect/pr59984.c: Require effective target vect_simd_clones.
2014-02-09 Paul Thomas <pault@gcc.gnu.org>
diff --git a/gcc/testsuite/c-c++-common/gomp/atomic-16.c b/gcc/testsuite/c-c++-common/gomp/atomic-16.c
index 87fbaa23317..9332396eaa5 100644
--- a/gcc/testsuite/c-c++-common/gomp/atomic-16.c
+++ b/gcc/testsuite/c-c++-common/gomp/atomic-16.c
@@ -7,28 +7,28 @@ void
foo ()
{
int v;
- #pragma omp atomic seq_cst load /* { dg-error "expected end of line" } */
- v = x; /* { dg-error "invalid form" } */
- #pragma omp atomic seq_cst, load /* { dg-error "expected end of line" } */
- v = x; /* { dg-error "invalid form" } */
- #pragma omp atomic seq_cst store /* { dg-error "expected end of line" } */
- x = v; /* { dg-error "invalid form" } */
- #pragma omp atomic seq_cst ,store /* { dg-error "expected end of line" } */
- x = v; /* { dg-error "invalid form" } */
- #pragma omp atomic seq_cst update /* { dg-error "expected end of line" } */
+ #pragma omp atomic seq_cst read
+ v = x;
+ #pragma omp atomic seq_cst, read
+ v = x;
+ #pragma omp atomic seq_cst write
+ x = v;
+ #pragma omp atomic seq_cst ,write
+ x = v;
+ #pragma omp atomic seq_cst update
x += v;
- #pragma omp atomic seq_cst , update /* { dg-error "expected end of line" } */
+ #pragma omp atomic seq_cst , update
x += v;
- #pragma omp atomic seq_cst capture /* { dg-error "expected end of line" } */
- v = x += 2; /* { dg-error "invalid form" } */
- #pragma omp atomic seq_cst, capture /* { dg-error "expected end of line" } */
- v = x += 2; /* { dg-error "invalid form" } */
- #pragma omp atomic load , seq_cst /* { dg-error "expected end of line" } */
- v = x; /* { dg-error "invalid form" } */
- #pragma omp atomic store ,seq_cst /* { dg-error "expected end of line" } */
- x = v; /* { dg-error "invalid form" } */
- #pragma omp atomic update, seq_cst /* { dg-error "expected end of line" } */
+ #pragma omp atomic seq_cst capture
+ v = x += 2;
+ #pragma omp atomic seq_cst, capture
+ v = x += 2;
+ #pragma omp atomic read , seq_cst
+ v = x;
+ #pragma omp atomic write ,seq_cst
+ x = v;
+ #pragma omp atomic update, seq_cst
x += v;
- #pragma omp atomic capture, seq_cst /* { dg-error "expected end of line" } */
+ #pragma omp atomic capture, seq_cst
v = x += 2;
}
diff --git a/gcc/testsuite/c-c++-common/gomp/pr60823-2.c b/gcc/testsuite/c-c++-common/gomp/pr60823-2.c
index e0bf570ddca..4c87620076a 100644
--- a/gcc/testsuite/c-c++-common/gomp/pr60823-2.c
+++ b/gcc/testsuite/c-c++-common/gomp/pr60823-2.c
@@ -1,5 +1,6 @@
/* PR tree-optimization/60823 */
/* { dg-do run } */
+/* { dg-require-effective-target vect_simd_clones } */
/* { dg-options "-O2 -fopenmp-simd" } */
#pragma omp declare simd simdlen(4) notinbranch
diff --git a/gcc/testsuite/c-c++-common/pr60156.c b/gcc/testsuite/c-c++-common/pr60156.c
new file mode 100644
index 00000000000..1e8204c99c7
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr60156.c
@@ -0,0 +1,9 @@
+/* PR c/60156 */
+/* { dg-do compile } */
+/* { dg-options "-Wpedantic" } */
+
+int
+main (int argc, char *argv[], ...) /* { dg-warning "declared as variadic function" } */
+{
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-43.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-43.C
new file mode 100644
index 00000000000..02eb33643ac
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-43.C
@@ -0,0 +1,4 @@
+// PR c++/59120
+// { dg-do compile { target c++11 } }
+
+template<typename T> using X = int T::T*; // { dg-error "expected" }
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/dwarf4-nested.C b/gcc/testsuite/g++.dg/debug/dwarf2/dwarf4-nested.C
new file mode 100644
index 00000000000..160694c3c9f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/dwarf4-nested.C
@@ -0,0 +1,55 @@
+// { dg-do compile }
+// { dg-options "--std=c++11 -dA -gdwarf-4 -fdebug-types-section -fno-merge-debug-strings" }
+
+// Check that -fdebug-types-sections does not copy a full referenced type
+// into a type unit.
+
+// Checks that at least one type unit is generated.
+//
+// { dg-final { scan-assembler "DIE \\(\[^\n\]*\\) DW_TAG_type_unit" } }
+//
+// Check that func is declared exactly once in the debug info (in the
+// compile unit).
+//
+// { dg-final { scan-assembler-times "\\.ascii \"func\\\\0\"\[^\n\]*DW_AT_name" 1 } }
+//
+// Check to make sure that no type unit contains a DIE with DW_AT_low_pc
+// or DW_AT_ranges. These patterns assume that the compile unit is always
+// emitted after all type units.
+//
+// { dg-final { scan-assembler-not "\\.quad\[^\n\]*DW_AT_low_pc.*DIE \\(\[^\n\]*\\) DW_TAG_compile_unit" } }
+// { dg-final { scan-assembler-not "\\.quad\[^\n\]*DW_AT_ranges.*DIE \\(\[^\n\]*\\) DW_TAG_compile_unit" } }
+
+struct A {
+ A();
+ virtual ~A();
+ virtual void foo();
+ private:
+ int data;
+};
+
+struct B {
+ B();
+ virtual ~B();
+};
+
+extern B* table[];
+
+struct D {
+ template <typename T>
+ T* get(int i)
+ {
+ B*& cell = table[i];
+ if (cell == 0)
+ cell = new T();
+ return static_cast<T*>(cell);
+ }
+};
+
+void func(D* d)
+{
+ struct C : B {
+ A a;
+ };
+ d->get<C>(0)->a.foo();
+}
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/dwarf4-typedef.C b/gcc/testsuite/g++.dg/debug/dwarf2/dwarf4-typedef.C
index c5520fa72b0..89a6bb44e10 100644
--- a/gcc/testsuite/g++.dg/debug/dwarf2/dwarf4-typedef.C
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/dwarf4-typedef.C
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-gdwarf-4" } */
+/* { dg-options "-gdwarf-4 -fdebug-types-section" } */
/* Regression test for an ICE in output_die when using -gdwarf-4. */
diff --git a/gcc/testsuite/g++.dg/ipa/devirt-27.C b/gcc/testsuite/g++.dg/ipa/devirt-27.C
index 1dcf76cc3c1..749f40af151 100644
--- a/gcc/testsuite/g++.dg/ipa/devirt-27.C
+++ b/gcc/testsuite/g++.dg/ipa/devirt-27.C
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O3 -fdump-ipa-devirt -fdump-tree-optimized" } */
+/* { dg-options "-O3 -fdump-tree-optimized" } */
struct A
{
int a;
diff --git a/gcc/testsuite/g++.dg/opt/pr60912.C b/gcc/testsuite/g++.dg/opt/pr60912.C
new file mode 100644
index 00000000000..ad51ba72570
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr60912.C
@@ -0,0 +1,18 @@
+// { dg-do run }
+// { dg-options "-O -fno-inline -fipa-pta" }
+
+struct IFoo
+{
+ virtual void Foo () = 0;
+};
+
+struct Bar:IFoo
+{
+ void Foo () {}
+};
+
+int main ()
+{
+ (new Bar ())->Foo ();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/vect/pr60896.cc b/gcc/testsuite/g++.dg/vect/pr60896.cc
new file mode 100644
index 00000000000..c6ce68b82a2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/vect/pr60896.cc
@@ -0,0 +1,44 @@
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+
+struct A
+{
+ int m_fn1 ();
+ short *m_fn2 ();
+};
+
+struct B
+{
+ void *fC;
+};
+
+int a, b;
+unsigned char i;
+void fn1 (unsigned char *p1, A &p2)
+{
+ int c = p2.m_fn1 ();
+ for (int d = 0; c; d++)
+ {
+ short *e = p2.m_fn2 ();
+ unsigned char *f = &p1[0];
+ for (int g = 0; g < a; g++)
+ {
+ int h = e[0];
+ b += h * f[g];
+ }
+ }
+}
+
+void fn2 (A &p1, A &p2, B &p3)
+{
+ int j = p2.m_fn1 ();
+ for (int k = 0; j; k++)
+ if (0)
+ ;
+ else
+ fn1 (&i, p1);
+ if (p3.fC)
+ ;
+ else
+ ;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/20140425-1.c b/gcc/testsuite/gcc.c-torture/execute/20140425-1.c
new file mode 100644
index 00000000000..c447ef95b6c
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/20140425-1.c
@@ -0,0 +1,23 @@
+/* PR target/60941 */
+/* Reported by Martin Husemann <martin@netbsd.org> */
+
+extern void abort (void);
+
+static void __attribute__((noinline))
+set (unsigned long *l)
+{
+ *l = 31;
+}
+
+int main (void)
+{
+ unsigned long l;
+ int i;
+
+ set (&l);
+ i = (int) l;
+ l = (unsigned long)(2U << i);
+ if (l != 0)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr60822.c b/gcc/testsuite/gcc.c-torture/execute/pr60822.c
new file mode 100644
index 00000000000..d2253310e69
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr60822.c
@@ -0,0 +1,24 @@
+struct X {
+ char fill0[800000];
+ int a;
+ char fill1[900000];
+ int b;
+};
+
+int __attribute__((noinline,noclone))
+Avg(struct X *p, int s)
+{
+ return (s * (long long)(p->a + p->b)) >> 17;
+}
+
+struct X x;
+
+int main()
+{
+ x.a = 1 << 17;
+ x.b = 2 << 17;
+ if (Avg(&x, 1) != 3)
+ __builtin_abort();
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr60822.x b/gcc/testsuite/gcc.c-torture/execute/pr60822.x
new file mode 100644
index 00000000000..4efed4c325f
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr60822.x
@@ -0,0 +1,7 @@
+load_lib target-supports.exp
+
+if { [check_effective_target_int32plus] } {
+ return 0
+}
+
+return 1;
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr60960.c b/gcc/testsuite/gcc.c-torture/execute/pr60960.c
new file mode 100644
index 00000000000..b4f08d4c543
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr60960.c
@@ -0,0 +1,38 @@
+/* PR tree-optimization/60960 */
+
+typedef unsigned char v4qi __attribute__ ((vector_size (4)));
+
+__attribute__((noinline, noclone)) v4qi
+f1 (v4qi v)
+{
+ return v / 2;
+}
+
+__attribute__((noinline, noclone)) v4qi
+f2 (v4qi v)
+{
+ return v / (v4qi) { 2, 2, 2, 2 };
+}
+
+__attribute__((noinline, noclone)) v4qi
+f3 (v4qi x, v4qi y)
+{
+ return x / y;
+}
+
+int
+main ()
+{
+ v4qi x = { 5, 5, 5, 5 };
+ v4qi y = { 2, 2, 2, 2 };
+ v4qi z = f1 (x);
+ if (__builtin_memcmp (&y, &z, sizeof (y)) != 0)
+ __builtin_abort ();
+ z = f2 (x);
+ if (__builtin_memcmp (&y, &z, sizeof (y)) != 0)
+ __builtin_abort ();
+ z = f3 (x, y);
+ if (__builtin_memcmp (&y, &z, sizeof (y)) != 0)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/Wstrict-overflow-14.c b/gcc/testsuite/gcc.dg/Wstrict-overflow-14.c
index 6f3c5a24fd1..dda07ea733b 100644
--- a/gcc/testsuite/gcc.dg/Wstrict-overflow-14.c
+++ b/gcc/testsuite/gcc.dg/Wstrict-overflow-14.c
@@ -10,6 +10,6 @@ foo (int j)
int sum = 0;
for (i = 1; i < j; i += i)
- sum += i / 16; /* { dg-warning "assuming signed overflow does not occur" "" } */
+ sum += i / 16; /* { dg-warning "assuming signed overflow does not occur" "" { xfail *-*-* } } */
return sum;
}
diff --git a/gcc/testsuite/gcc.dg/Wstrict-overflow-15.c b/gcc/testsuite/gcc.dg/Wstrict-overflow-15.c
index d1627d2f47b..c9e275c0bd6 100644
--- a/gcc/testsuite/gcc.dg/Wstrict-overflow-15.c
+++ b/gcc/testsuite/gcc.dg/Wstrict-overflow-15.c
@@ -10,6 +10,6 @@ foo (int j)
int sum = 0;
for (i = 1; i < j; i += i)
- sum += __builtin_abs (i); /* { dg-warning "assuming signed overflow does not occur" "" } */
+ sum += __builtin_abs (i); /* { dg-warning "assuming signed overflow does not occur" "" { xfail *-*-* } } */
return sum;
}
diff --git a/gcc/testsuite/gcc.dg/Wstrict-overflow-18.c b/gcc/testsuite/gcc.dg/Wstrict-overflow-18.c
index 2767c44fbf2..7bf111a50ea 100644
--- a/gcc/testsuite/gcc.dg/Wstrict-overflow-18.c
+++ b/gcc/testsuite/gcc.dg/Wstrict-overflow-18.c
@@ -17,7 +17,7 @@ foo (struct c *p)
for (i = 0; i < p->a - p->b; ++i)
{
- if (i > 0) /* { dg-bogus "warning" "" { xfail *-*-* } } */
+ if (i > 0) /* { dg-bogus "warning" "" } */
sum += 2;
bar (p);
}
diff --git a/gcc/testsuite/gcc.dg/graphite/pr60979.c b/gcc/testsuite/gcc.dg/graphite/pr60979.c
new file mode 100644
index 00000000000..0004a51248d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/graphite/pr60979.c
@@ -0,0 +1,37 @@
+/* { dg-options "-O -fgraphite-identity" } */
+
+#include <setjmp.h>
+
+struct x;
+
+typedef struct x **(*a)(struct x *);
+
+struct x {
+ union {
+ struct {
+ union {
+ a *i;
+ } l;
+ int s;
+ } y;
+ } e;
+};
+
+jmp_buf c;
+
+void
+b(struct x *r)
+{
+ int f;
+ static int w = 0;
+ volatile jmp_buf m;
+ f = (*(((struct x *)r)->e.y.l.i[2]((struct x *)r)))->e.y.s;
+ if (w++ != 0)
+ __builtin_memcpy((char *)m, (const char *)c, sizeof(jmp_buf));
+ if (setjmp (c) == 0) {
+ int z;
+ for (z = 0; z < 0; ++z)
+ ;
+ }
+ d((const char *)m);
+}
diff --git a/gcc/testsuite/gcc.dg/lto/pr60911_0.c b/gcc/testsuite/gcc.dg/lto/pr60911_0.c
new file mode 100644
index 00000000000..e4820a20497
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/pr60911_0.c
@@ -0,0 +1,21 @@
+// { dg-lto-do run }
+// { dg-lto-options { { -O2 -flto -fipa-pta } } }
+
+int __attribute__ ((__noinline__)) f (unsigned *p, int *x)
+{
+ int y = *p++ & 0xfff;
+ *x++ = y;
+ *x = *p;
+ return y;
+}
+
+int
+main ()
+{
+ unsigned u[2] = { 0x3aad, 0x5ad1 };
+ int x[2] = { 17689, 23456 };
+
+ if (f (u, x) != 0xaad || x[0] != 0xaad || x[1] != 0x5ad1)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr18079-2.c b/gcc/testsuite/gcc.dg/pr18079-2.c
new file mode 100644
index 00000000000..2c83b701e10
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr18079-2.c
@@ -0,0 +1,16 @@
+/* PR c/18079 */
+/* { dg-do compile } */
+/* { dg-options "-Wall" } */
+
+__attribute__ ((always_inline)) void fndecl1 (void);
+__attribute__ ((noinline)) void fndecl1 (void); /* { dg-warning "attribute 'noinline' follows declaration with attribute 'always_inline'" } */
+
+__attribute__ ((noinline)) void fndecl2 (void);
+__attribute__ ((always_inline)) void fndecl2 (void); /* { dg-warning "attribute 'always_inline' follows declaration with attribute 'noinline'" } */
+
+
+__attribute__ ((hot)) void fndecl3 (void);
+__attribute__ ((cold)) void fndecl3 (void); /* { dg-warning "attribute 'cold' follows declaration with attribute 'hot'" } */
+
+__attribute__ ((cold)) void fndecl4 (void);
+__attribute__ ((hot)) void fndecl4 (void); /* { dg-warning "attribute 'hot' follows declaration with attribute 'cold'" } */
diff --git a/gcc/testsuite/gcc.dg/pr18079.c b/gcc/testsuite/gcc.dg/pr18079.c
new file mode 100644
index 00000000000..b84cdebde3f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr18079.c
@@ -0,0 +1,33 @@
+/* PR c/18079 */
+/* { dg-do compile } */
+/* { dg-options "-Wall" } */
+
+__attribute__ ((noinline))
+__attribute__ ((always_inline))
+int
+fn1 (int r)
+{ /* { dg-warning "attribute ignored due to conflict" } */
+ return r & 4;
+}
+
+__attribute__ ((noinline, always_inline))
+int
+fn2 (int r)
+{ /* { dg-warning "attribute ignored due to conflict" } */
+ return r & 4;
+}
+
+__attribute__ ((always_inline))
+__attribute__ ((noinline))
+inline int
+fn3 (int r)
+{ /* { dg-warning "attribute ignored due to conflict" } */
+ return r & 8;
+}
+
+__attribute__ ((always_inline, noinline))
+inline int
+fn4 (int r)
+{ /* { dg-warning "attribute ignored due to conflict" } */
+ return r & 8;
+}
diff --git a/gcc/testsuite/gcc.dg/pr60114.c b/gcc/testsuite/gcc.dg/pr60114.c
new file mode 100644
index 00000000000..c656a9586aa
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr60114.c
@@ -0,0 +1,31 @@
+/* PR c/60114 */
+/* { dg-do compile } */
+/* { dg-options "-Wconversion" } */
+
+struct S { int n, u[2]; };
+const signed char z[] = {
+ [0] = 0x100, /* { dg-warning "9:overflow in implicit constant conversion" } */
+ [2] = 0x101, /* { dg-warning "9:overflow in implicit constant conversion" } */
+};
+int A[] = {
+ 0, 0x80000000, /* { dg-warning "16:conversion of unsigned constant value to negative integer" } */
+ 0xA, 0x80000000, /* { dg-warning "18:conversion of unsigned constant value to negative integer" } */
+ 0xA, 0xA, 0x80000000 /* { dg-warning "23:conversion of unsigned constant value to negative integer" } */
+ };
+int *p = (int []) { 0x80000000 }; /* { dg-warning "21:conversion of unsigned constant value to negative integer" } */
+union { int k; } u = { .k = 0x80000000 }; /* { dg-warning "29:conversion of unsigned constant value to negative integer" } */
+typedef int H[];
+void
+foo (void)
+{
+ signed char a[][3] = { { 0x100, /* { dg-warning "28:overflow in implicit constant conversion" } */
+ 1, 0x100 }, /* { dg-warning "24:overflow in implicit constant conversion" } */
+ { '\0', 0x100, '\0' } /* { dg-warning "27:overflow in implicit constant conversion" } */
+ };
+ (const signed char []) { 0x100 }; /* { dg-warning "28:overflow in implicit constant conversion" } */
+ (const float []) { 1e0, 1e1, 1e100 }; /* { dg-warning "32:conversion" } */
+ struct S s1 = { 0x80000000 }; /* { dg-warning "19:conversion of unsigned constant value to negative integer" } */
+ struct S s2 = { .n = 0x80000000 }; /* { dg-warning "24:conversion of unsigned constant value to negative integer" } */
+ struct S s3 = { .u[1] = 0x80000000 }; /* { dg-warning "27:conversion of unsigned constant value to negative integer" } */
+ H h = { 1, 2, 0x80000000 }; /* { dg-warning "17:conversion of unsigned constant value to negative integer" } */
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr60930.c b/gcc/testsuite/gcc.dg/torture/pr60930.c
new file mode 100644
index 00000000000..5e35f19882d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr60930.c
@@ -0,0 +1,22 @@
+/* { dg-do run } */
+
+int x = 1;
+
+__attribute__((noinline, noclone)) void
+foo (unsigned long long t)
+{
+ asm volatile ("" : : "r" (&t));
+ if (t == 1)
+ __builtin_abort ();
+}
+
+int
+main ()
+{
+#if __SIZEOF_LONG_LONG__ >= 8
+ unsigned long long t = 0xffffffffffffffffULL * (0xffffffffUL * x);
+ if (t != 0xffffffff00000001ULL)
+ foo (t);;
+#endif
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-30.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-30.c
index addf1284057..7ef830d1937 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/alias-30.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-30.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O -fdump-tree-fre-details" } */
+/* { dg-options "-O -fdump-tree-fre1-details" } */
extern int posix_memalign(void **memptr,
__SIZE_TYPE__ alignment, __SIZE_TYPE__ size);
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/isolate-1.c b/gcc/testsuite/gcc.dg/tree-ssa/isolate-1.c
index f1f3101d3d2..3ed98aeb857 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/isolate-1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/isolate-1.c
@@ -1,6 +1,7 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-isolate-paths" } */
+/* { dg-skip-if "" keeps_null_pointer_checks } */
struct demangle_component
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/isolate-2.c b/gcc/testsuite/gcc.dg/tree-ssa/isolate-2.c
index bfcaa2b01da..912d98e2246 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/isolate-2.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/isolate-2.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fisolate-erroneous-paths-attribute -fdump-tree-isolate-paths -fdump-tree-phicprop1" } */
+/* { dg-skip-if "" keeps_null_pointer_checks } */
int z;
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/isolate-3.c b/gcc/testsuite/gcc.dg/tree-ssa/isolate-3.c
index 7dddd8062c0..9c2c5d55c27 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/isolate-3.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/isolate-3.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-isolate-paths" } */
+/* { dg-skip-if "" keeps_null_pointer_checks } */
typedef long unsigned int size_t;
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/isolate-4.c b/gcc/testsuite/gcc.dg/tree-ssa/isolate-4.c
index c9c074df62b..d50a2b27f47 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/isolate-4.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/isolate-4.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fisolate-erroneous-paths-attribute -fdump-tree-isolate-paths -fdump-tree-phicprop1" } */
+/* { dg-skip-if "" keeps_null_pointer_checks } */
extern void foo(void *) __attribute__ ((__nonnull__ (1)));
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/isolate-5.c b/gcc/testsuite/gcc.dg/tree-ssa/isolate-5.c
index 4d01d5c6399..e6ae37a7f74 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/isolate-5.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/isolate-5.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-isolate-paths -fdump-tree-optimized" } */
+/* { dg-skip-if "" keeps_null_pointer_checks } */
struct demangle_component
{
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp91.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp91.c
new file mode 100644
index 00000000000..68d8fd33a0b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp91.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-S -O2 -fdump-tree-vrp2" } */
+
+unsigned short data;
+void foo ()
+{
+ unsigned char x16;
+ unsigned int i;
+ for (i = 0; i < 8; i++)
+ {
+ x16 = data & 1;
+ data >>= 1;
+ if (x16 == 1)
+ {
+ data ^= 0x4;
+ }
+ data >>= 1;
+ }
+}
+
+/* { dg-final { scan-tree-dump "\\\[0, 7\\\]" "vrp2" } } */
+/* { dg-final { cleanup-tree-dump "vrp2" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/pr60505.c b/gcc/testsuite/gcc.dg/vect/pr60505.c
index 694051320ce..70e2ec06fe5 100644
--- a/gcc/testsuite/gcc.dg/vect/pr60505.c
+++ b/gcc/testsuite/gcc.dg/vect/pr60505.c
@@ -10,3 +10,5 @@ void foo(char *in, char *out, int num)
out[i] = (ovec[i] = in[i]);
out[num] = ovec[num/2];
}
+
+/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.target/arm/tail-long-call.c b/gcc/testsuite/gcc.target/arm/tail-long-call.c
new file mode 100644
index 00000000000..9b274686849
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/tail-long-call.c
@@ -0,0 +1,12 @@
+/* { dg-skip-if "need at least armv5te" { *-*-* } { "-march=armv[234]*" "-mthumb" } { "" } } */
+/* { dg-options "-O2 -march=armv5te -marm" } */
+/* { dg-final { scan-assembler "bx" } } */
+/* { dg-final { scan-assembler-not "blx" } } */
+
+int lcal (int) __attribute__ ((long_call));
+
+int
+dec (int a)
+{
+ return lcal (a);
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/bcd-1.c b/gcc/testsuite/gcc.target/powerpc/bcd-1.c
new file mode 100644
index 00000000000..c7496c23579
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bcd-1.c
@@ -0,0 +1,27 @@
+/* { dg-do compile { target { powerpc*-*-linux* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-mcpu=power7 -O2" } */
+/* { dg-final { scan-assembler-times "cdtbcd " 1 } } */
+/* { dg-final { scan-assembler-times "cbcdtd " 1 } } */
+/* { dg-final { scan-assembler-times "addg6s " 1 } } */
+/* { dg-final { scan-assembler-not "bl __builtin" } } */
+
+unsigned int
+to_bcd (unsigned int a)
+{
+ return __builtin_cdtbcd (a);
+}
+
+unsigned int
+from_bcd (unsigned int a)
+{
+ return __builtin_cbcdtd (a);
+}
+
+unsigned int
+bcd_arith (unsigned int a, unsigned int b)
+{
+ return __builtin_addg6s (a, b);
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/bcd-2.c b/gcc/testsuite/gcc.target/powerpc/bcd-2.c
new file mode 100644
index 00000000000..d330b742376
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bcd-2.c
@@ -0,0 +1,44 @@
+/* { dg-do compile { target { powerpc*-*-linux* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-options "-mcpu=power8 -O2" } */
+/* { dg-final { scan-assembler-times "bcdadd\[.\] " 2 } } */
+/* { dg-final { scan-assembler-times "bcdsub\[.\] " 2 } } */
+/* { dg-final { scan-assembler-not "bl __builtin" } } */
+/* { dg-final { scan-assembler-not "mtvsr" } } */
+/* { dg-final { scan-assembler-not "mfvsr" } } */
+/* { dg-final { scan-assembler-not "lvx" } } */
+/* { dg-final { scan-assembler-not "lxvw4x" } } */
+/* { dg-final { scan-assembler-not "lxvd2x" } } */
+/* { dg-final { scan-assembler-not "stvx" } } */
+/* { dg-final { scan-assembler-not "stxvw4x" } } */
+/* { dg-final { scan-assembler-not "stxvd2x" } } */
+
+typedef __int128_t __attribute__((__vector_size__(16))) vector_128_t;
+typedef __int128_t scalar_128_t;
+typedef unsigned long long scalar_64_t;
+
+vector_128_t
+do_add_0 (vector_128_t a, vector_128_t b)
+{
+ return __builtin_bcdadd (a, b, 0);
+}
+
+vector_128_t
+do_add_1 (vector_128_t a, vector_128_t b)
+{
+ return __builtin_bcdadd (a, b, 1);
+}
+
+vector_128_t
+do_sub_0 (vector_128_t a, vector_128_t b)
+{
+ return __builtin_bcdsub (a, b, 0);
+}
+
+vector_128_t
+do_sub_1 (vector_128_t a, vector_128_t b)
+{
+ return __builtin_bcdsub (a, b, 1);
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/bcd-3.c b/gcc/testsuite/gcc.target/powerpc/bcd-3.c
new file mode 100644
index 00000000000..436cecf6fff
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bcd-3.c
@@ -0,0 +1,103 @@
+/* { dg-do compile { target { powerpc*-*-linux* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-options "-mcpu=power8 -O2" } */
+/* { dg-final { scan-assembler-times "bcdadd\[.\] " 4 } } */
+/* { dg-final { scan-assembler-times "bcdsub\[.\] " 4 } } */
+/* { dg-final { scan-assembler-not "bl __builtin" } } */
+/* { dg-final { scan-assembler-not "mtvsr" } } */
+/* { dg-final { scan-assembler-not "mfvsr" } } */
+/* { dg-final { scan-assembler-not "lvx" } } */
+/* { dg-final { scan-assembler-not "lxvw4x" } } */
+/* { dg-final { scan-assembler-not "lxvd2x" } } */
+/* { dg-final { scan-assembler-not "stvx" } } */
+/* { dg-final { scan-assembler-not "stxvw4x" } } */
+/* { dg-final { scan-assembler-not "stxvd2x" } } */
+
+typedef __int128_t __attribute__((__vector_size__(16))) vector_128_t;
+typedef __int128_t scalar_128_t;
+typedef unsigned long long scalar_64_t;
+
+/* Test whether the peephole works to allow folding a bcdadd, with a
+ bcdadd_<test> into a single instruction. */
+
+vector_128_t
+do_add_lt (vector_128_t a, vector_128_t b, int *p)
+{
+ vector_128_t ret = __builtin_bcdadd (a, b, 0);
+ if (__builtin_bcdadd_lt (a, b, 0))
+ *p = 1;
+
+ return ret;
+}
+
+vector_128_t
+do_add_eq (vector_128_t a, vector_128_t b, int *p)
+{
+ vector_128_t ret = __builtin_bcdadd (a, b, 0);
+ if (__builtin_bcdadd_eq (a, b, 0))
+ *p = 1;
+
+ return ret;
+}
+
+vector_128_t
+do_add_gt (vector_128_t a, vector_128_t b, int *p)
+{
+ vector_128_t ret = __builtin_bcdadd (a, b, 0);
+ if (__builtin_bcdadd_gt (a, b, 0))
+ *p = 1;
+
+ return ret;
+}
+
+vector_128_t
+do_add_ov (vector_128_t a, vector_128_t b, int *p)
+{
+ vector_128_t ret = __builtin_bcdadd (a, b, 0);
+ if (__builtin_bcdadd_ov (a, b, 0))
+ *p = 1;
+
+ return ret;
+}
+
+vector_128_t
+do_sub_lt (vector_128_t a, vector_128_t b, int *p)
+{
+ vector_128_t ret = __builtin_bcdsub (a, b, 0);
+ if (__builtin_bcdsub_lt (a, b, 0))
+ *p = 1;
+
+ return ret;
+}
+
+vector_128_t
+do_sub_eq (vector_128_t a, vector_128_t b, int *p)
+{
+ vector_128_t ret = __builtin_bcdsub (a, b, 0);
+ if (__builtin_bcdsub_eq (a, b, 0))
+ *p = 1;
+
+ return ret;
+}
+
+vector_128_t
+do_sub_gt (vector_128_t a, vector_128_t b, int *p)
+{
+ vector_128_t ret = __builtin_bcdsub (a, b, 0);
+ if (__builtin_bcdsub_gt (a, b, 0))
+ *p = 1;
+
+ return ret;
+}
+
+vector_128_t
+do_sub_ov (vector_128_t a, vector_128_t b, int *p)
+{
+ vector_128_t ret = __builtin_bcdsub (a, b, 0);
+ if (__builtin_bcdsub_ov (a, b, 0))
+ *p = 1;
+
+ return ret;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/dfp-builtin-1.c b/gcc/testsuite/gcc.target/powerpc/dfp-builtin-1.c
new file mode 100644
index 00000000000..614f272642c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/dfp-builtin-1.c
@@ -0,0 +1,88 @@
+/* { dg-do compile { target { powerpc*-*-linux* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-mcpu=power7 -O2" } */
+/* { dg-final { scan-assembler-times "ddedpd " 4 } } */
+/* { dg-final { scan-assembler-times "denbcd " 2 } } */
+/* { dg-final { scan-assembler-times "dxex " 1 } } */
+/* { dg-final { scan-assembler-times "diex " 1 } } */
+/* { dg-final { scan-assembler-times "dscli " 2 } } */
+/* { dg-final { scan-assembler-times "dscri " 2 } } */
+/* { dg-final { scan-assembler-not "bl __builtin" } } */
+/* { dg-final { scan-assembler-not "dctqpq" } } */
+/* { dg-final { scan-assembler-not "drdpq" } } */
+/* { dg-final { scan-assembler-not "stfd" } } */
+/* { dg-final { scan-assembler-not "lfd" } } */
+
+_Decimal64
+do_dedpd_0 (_Decimal64 a)
+{
+ return __builtin_ddedpd (0, a);
+}
+
+_Decimal64
+do_dedpd_1 (_Decimal64 a)
+{
+ return __builtin_ddedpd (1, a);
+}
+
+_Decimal64
+do_dedpd_2 (_Decimal64 a)
+{
+ return __builtin_ddedpd (2, a);
+}
+
+_Decimal64
+do_dedpd_3 (_Decimal64 a)
+{
+ return __builtin_ddedpd (3, a);
+}
+
+_Decimal64
+do_enbcd_0 (_Decimal64 a)
+{
+ return __builtin_denbcd (0, a);
+}
+
+_Decimal64
+do_enbcd_1 (_Decimal64 a)
+{
+ return __builtin_denbcd (1, a);
+}
+
+_Decimal64
+do_xex (_Decimal64 a)
+{
+ return __builtin_dxex (a);
+}
+
+_Decimal64
+do_iex (_Decimal64 a, _Decimal64 b)
+{
+ return __builtin_diex (a, b);
+}
+
+_Decimal64
+do_scli_1 (_Decimal64 a)
+{
+ return __builtin_dscli (a, 1);
+}
+
+_Decimal64
+do_scli_10 (_Decimal64 a)
+{
+ return __builtin_dscli (a, 10);
+}
+
+_Decimal64
+do_scri_1 (_Decimal64 a)
+{
+ return __builtin_dscri (a, 1);
+}
+
+_Decimal64
+do_scri_10 (_Decimal64 a)
+{
+ return __builtin_dscri (a, 10);
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/dfp-builtin-2.c b/gcc/testsuite/gcc.target/powerpc/dfp-builtin-2.c
new file mode 100644
index 00000000000..189bc9ad6ae
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/dfp-builtin-2.c
@@ -0,0 +1,88 @@
+/* { dg-do compile { target { powerpc*-*-linux* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-mcpu=power7 -O2" } */
+/* { dg-final { scan-assembler-times "ddedpdq " 4 } } */
+/* { dg-final { scan-assembler-times "denbcdq " 2 } } */
+/* { dg-final { scan-assembler-times "dxexq " 1 } } */
+/* { dg-final { scan-assembler-times "diexq " 1 } } */
+/* { dg-final { scan-assembler-times "dscliq " 2 } } */
+/* { dg-final { scan-assembler-times "dscriq " 2 } } */
+/* { dg-final { scan-assembler-not "bl __builtin" } } */
+/* { dg-final { scan-assembler-not "dctqpq" } } */
+/* { dg-final { scan-assembler-not "drdpq" } } */
+/* { dg-final { scan-assembler-not "stfd" } } */
+/* { dg-final { scan-assembler-not "lfd" } } */
+
+_Decimal128
+do_dedpdq_0 (_Decimal128 a)
+{
+ return __builtin_ddedpdq (0, a);
+}
+
+_Decimal128
+do_dedpdq_1 (_Decimal128 a)
+{
+ return __builtin_ddedpdq (1, a);
+}
+
+_Decimal128
+do_dedpdq_2 (_Decimal128 a)
+{
+ return __builtin_ddedpdq (2, a);
+}
+
+_Decimal128
+do_dedpdq_3 (_Decimal128 a)
+{
+ return __builtin_ddedpdq (3, a);
+}
+
+_Decimal128
+do_enbcdq_0 (_Decimal128 a)
+{
+ return __builtin_denbcdq (0, a);
+}
+
+_Decimal128
+do_enbcdq_1 (_Decimal128 a)
+{
+ return __builtin_denbcdq (1, a);
+}
+
+_Decimal128
+do_xexq (_Decimal128 a)
+{
+ return __builtin_dxexq (a);
+}
+
+_Decimal128
+do_iexq (_Decimal128 a, _Decimal128 b)
+{
+ return __builtin_diexq (a, b);
+}
+
+_Decimal128
+do_scliq_1 (_Decimal128 a)
+{
+ return __builtin_dscliq (a, 1);
+}
+
+_Decimal128
+do_scliq_10 (_Decimal128 a)
+{
+ return __builtin_dscliq (a, 10);
+}
+
+_Decimal128
+do_scriq_1 (_Decimal128 a)
+{
+ return __builtin_dscriq (a, 1);
+}
+
+_Decimal128
+do_scriq_10 (_Decimal128 a)
+{
+ return __builtin_dscriq (a, 10);
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/extend-divide-1.c b/gcc/testsuite/gcc.target/powerpc/extend-divide-1.c
new file mode 100644
index 00000000000..5f948b7212f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/extend-divide-1.c
@@ -0,0 +1,34 @@
+/* { dg-do compile { target { powerpc*-*-linux* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-mcpu=power7 -O2" } */
+/* { dg-final { scan-assembler-times "divwe " 1 } } */
+/* { dg-final { scan-assembler-times "divweo " 1 } } */
+/* { dg-final { scan-assembler-times "divweu " 1 } } */
+/* { dg-final { scan-assembler-times "divweuo " 1 } } */
+/* { dg-final { scan-assembler-not "bl __builtin" } } */
+
+int
+div_we (int a, int b)
+{
+ return __builtin_divwe (a, b);
+}
+
+int
+div_weo (int a, int b)
+{
+ return __builtin_divweo (a, b);
+}
+
+unsigned int
+div_weu (unsigned int a, unsigned int b)
+{
+ return __builtin_divweu (a, b);
+}
+
+unsigned int
+div_weuo (unsigned int a, unsigned int b)
+{
+ return __builtin_divweuo (a, b);
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/extend-divide-2.c b/gcc/testsuite/gcc.target/powerpc/extend-divide-2.c
new file mode 100644
index 00000000000..8ee6c8cf768
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/extend-divide-2.c
@@ -0,0 +1,34 @@
+/* { dg-do compile { target { powerpc*-*-linux* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-mcpu=power7 -O2" } */
+/* { dg-final { scan-assembler-times "divde " 1 } } */
+/* { dg-final { scan-assembler-times "divdeo " 1 } } */
+/* { dg-final { scan-assembler-times "divdeu " 1 } } */
+/* { dg-final { scan-assembler-times "divdeuo " 1 } } */
+/* { dg-final { scan-assembler-not "bl __builtin" } } */
+
+long
+div_de (long a, long b)
+{
+ return __builtin_divde (a, b);
+}
+
+long
+div_deo (long a, long b)
+{
+ return __builtin_divdeo (a, b);
+}
+
+unsigned long
+div_deu (unsigned long a, unsigned long b)
+{
+ return __builtin_divdeu (a, b);
+}
+
+unsigned long
+div_deuo (unsigned long a, unsigned long b)
+{
+ return __builtin_divdeuo (a, b);
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/pack01.c b/gcc/testsuite/gcc.target/powerpc/pack01.c
new file mode 100644
index 00000000000..efac4087c78
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pack01.c
@@ -0,0 +1,91 @@
+/* { dg-do run { target { powerpc*-*-linux* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */
+/* { dg-require-effective-target p8vector_hw } */
+/* { dg-options "-mcpu=power8 -O2" } */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <altivec.h>
+
+#ifdef DEBUG
+#include <stdio.h>
+#endif
+
+typedef __int128_t __attribute__((__vector_size__(16))) vector_128_t;
+typedef __int128_t scalar_128_t;
+typedef unsigned long long scalar_64_t;
+
+volatile scalar_64_t one = 1;
+volatile scalar_64_t two = 2;
+
+int
+main (void)
+{
+ scalar_128_t a = (((scalar_128_t)one) << 64) | ((scalar_128_t)two);
+ vector_128_t v1 = (vector_128_t) { a };
+ vector_128_t v2 = __builtin_pack_vector_int128 (one, two);
+ scalar_64_t x0 = __builtin_unpack_vector_int128 (v1, 0);
+ scalar_64_t x1 = __builtin_unpack_vector_int128 (v1, 1);
+ vector_128_t v3 = __builtin_pack_vector_int128 (x0, x1);
+
+ size_t i;
+ union {
+ scalar_128_t i128;
+ vector_128_t v128;
+ scalar_64_t u64;
+ unsigned char uc[sizeof (scalar_128_t)];
+ char c[sizeof (scalar_128_t)];
+ } u, u2;
+
+#ifdef DEBUG
+ {
+ printf ("a = 0x");
+ u.i128 = a;
+ for (i = 0; i < sizeof (scalar_128_t); i++)
+ printf ("%.2x", u.uc[i]);
+
+ printf ("\nv1 = 0x");
+ u.v128 = v1;
+ for (i = 0; i < sizeof (scalar_128_t); i++)
+ printf ("%.2x", u.uc[i]);
+
+ printf ("\nv2 = 0x");
+ u.v128 = v2;
+ for (i = 0; i < sizeof (scalar_128_t); i++)
+ printf ("%.2x", u.uc[i]);
+
+ printf ("\nv3 = 0x");
+ u.v128 = v3;
+ for (i = 0; i < sizeof (scalar_128_t); i++)
+ printf ("%.2x", u.uc[i]);
+
+ printf ("\nx0 = 0x");
+ u.u64 = x0;
+ for (i = 0; i < sizeof (scalar_64_t); i++)
+ printf ("%.2x", u.uc[i]);
+
+ printf ("\nx1 = 0x");
+ u.u64 = x1;
+ for (i = 0; i < sizeof (scalar_64_t); i++)
+ printf ("%.2x", u.uc[i]);
+
+ printf ("\n");
+ }
+#endif
+
+ u2.i128 = a;
+ u.v128 = v1;
+ if (memcmp (u.c, u2.c, sizeof (scalar_128_t)) != 0)
+ abort ();
+
+ u.v128 = v2;
+ if (memcmp (u.c, u2.c, sizeof (scalar_128_t)) != 0)
+ abort ();
+
+ u.v128 = v3;
+ if (memcmp (u.c, u2.c, sizeof (scalar_128_t)) != 0)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/pack02.c b/gcc/testsuite/gcc.target/powerpc/pack02.c
new file mode 100644
index 00000000000..74b6cd04dcc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pack02.c
@@ -0,0 +1,95 @@
+/* { dg-do run { target { powerpc*-*-linux* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-options "-O2" } */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <math.h>
+
+#ifdef DEBUG
+#include <stdio.h>
+#endif
+
+int
+main (void)
+{
+ double high = pow (2.0, 60);
+ double low = 2.0;
+ long double a = ((long double)high) + ((long double)low);
+ double x0 = __builtin_unpack_longdouble (a, 0);
+ double x1 = __builtin_unpack_longdouble (a, 1);
+ long double b = __builtin_pack_longdouble (x0, x1);
+
+#ifdef DEBUG
+ {
+ size_t i;
+ union {
+ long double ld;
+ double d;
+ unsigned char uc[sizeof (long double)];
+ char c[sizeof (long double)];
+ } u;
+
+ printf ("a = 0x");
+ u.ld = a;
+ for (i = 0; i < sizeof (long double); i++)
+ printf ("%.2x", u.uc[i]);
+
+ printf (", %Lg\n", a);
+
+ printf ("b = 0x");
+ u.ld = b;
+ for (i = 0; i < sizeof (long double); i++)
+ printf ("%.2x", u.uc[i]);
+
+ printf (", %Lg\n", b);
+
+ printf ("hi = 0x");
+ u.d = high;
+ for (i = 0; i < sizeof (double); i++)
+ printf ("%.2x", u.uc[i]);
+
+ printf (",%*s %g\n", (int)(2 * (sizeof (long double) - sizeof (double))), "", high);
+
+ printf ("lo = 0x");
+ u.d = low;
+ for (i = 0; i < sizeof (double); i++)
+ printf ("%.2x", u.uc[i]);
+
+ printf (",%*s %g\n", (int)(2 * (sizeof (long double) - sizeof (double))), "", low);
+
+ printf ("x0 = 0x");
+ u.d = x0;
+ for (i = 0; i < sizeof (double); i++)
+ printf ("%.2x", u.uc[i]);
+
+ printf (",%*s %g\n", (int)(2 * (sizeof (long double) - sizeof (double))), "", x0);
+
+ printf ("x1 = 0x");
+ u.d = x1;
+ for (i = 0; i < sizeof (double); i++)
+ printf ("%.2x", u.uc[i]);
+
+ printf (",%*s %g\n", (int)(2 * (sizeof (long double) - sizeof (double))), "", x1);
+ }
+#endif
+
+ if (high != x0)
+ abort ();
+
+ if (low != x1)
+ abort ();
+
+ if (a != b)
+ abort ();
+
+ if (x0 != high)
+ abort ();
+
+ if (x1 != low)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/pack03.c b/gcc/testsuite/gcc.target/powerpc/pack03.c
new file mode 100644
index 00000000000..59f0e74ba9c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pack03.c
@@ -0,0 +1,88 @@
+/* { dg-do run { target { powerpc*-*-linux* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-options "-O2" } */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <math.h>
+
+#ifdef DEBUG
+#include <stdio.h>
+#endif
+
+int
+main (void)
+{
+ _Decimal128 one = (_Decimal128)1.0;
+ _Decimal128 two = (_Decimal128)2.0;
+ _Decimal128 ten = (_Decimal128)10.0;
+ _Decimal128 a = one;
+ _Decimal128 b;
+ _Decimal128 c;
+ unsigned long long x0;
+ unsigned long long x1;
+ size_t i;
+
+ for (i = 0; i < 25; i++)
+ a *= ten;
+
+ a += two;
+
+ x0 = __builtin_unpack_dec128 (a, 0);
+ x1 = __builtin_unpack_dec128 (a, 1);
+ b = __builtin_pack_dec128 (x0, x1);
+ c = __builtin_dscliq (one, 25) + two;
+
+#ifdef DEBUG
+ {
+ union {
+ _Decimal128 d;
+ unsigned long long ull;
+ unsigned char uc[sizeof (_Decimal128)];
+ } u;
+
+ printf ("a = 0x");
+ u.d = a;
+ for (i = 0; i < sizeof (_Decimal128); i++)
+ printf ("%.2x", u.uc[i]);
+
+ printf (", %Lg\n", (long double)a);
+
+ printf ("b = 0x");
+ u.d = b;
+ for (i = 0; i < sizeof (_Decimal128); i++)
+ printf ("%.2x", u.uc[i]);
+
+ printf (", %Lg\n", (long double)b);
+
+ printf ("c = 0x");
+ u.d = c;
+ for (i = 0; i < sizeof (_Decimal128); i++)
+ printf ("%.2x", u.uc[i]);
+
+ printf (", %Lg\n", (long double)c);
+
+ printf ("x0 = 0x");
+ u.ull = x0;
+ for (i = 0; i < sizeof (unsigned long long); i++)
+ printf ("%.2x", u.uc[i]);
+
+ printf ("\nx1 = 0x");
+ u.ull = x1;
+ for (i = 0; i < sizeof (unsigned long long); i++)
+ printf ("%.2x", u.uc[i]);
+
+ printf ("\n");
+ }
+#endif
+
+ if (a != b)
+ abort ();
+
+ if (a != c)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gfortran.dg/namelist_utf8.f90 b/gcc/testsuite/gfortran.dg/namelist_utf8.f90
new file mode 100644
index 00000000000..c494b8c3b77
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/namelist_utf8.f90
@@ -0,0 +1,30 @@
+! { dg-do run }
+! PR52539 UTF-8 support for namelist read and write
+
+character(len=10, kind=4) :: str, str2
+character(len=25, kind=4) :: str3
+
+namelist /nml/ str
+
+str = 4_'a'//char (int (z'4F60'),4) &
+ //char (int (z'597D'), 4)//4_'b'
+
+open(99, encoding='utf-8',form='formatted')
+write(99, '(3a)') '&nml str = "', str, '" /'
+write(99, '(a)') str
+rewind(99)
+
+str = 4_'XXXX'
+str2 = 4_'YYYY'
+read(99,nml=nml)
+read(99, *) str2
+if (str2 /= str) call abort
+rewind(99)
+
+read(99,'(A)') str3
+if (str3 /= 4_'&nml str = "' // str // 4_'" /') call abort
+read(99,'(A)') str3
+if (str3 /= str) call abort
+
+close(99, status='delete')
+end
diff --git a/gcc/testsuite/gfortran.dg/no_range_check_3.f90 b/gcc/testsuite/gfortran.dg/no_range_check_3.f90
new file mode 100644
index 00000000000..24223af5b38
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/no_range_check_3.f90
@@ -0,0 +1,12 @@
+! { dg-do run }
+! { dg-options "-fno-range-check" }
+program test
+ integer :: i
+ i = int(z'FFFFFFFF',kind(i))
+ if (i /= -1) call abort
+ if (int(z'FFFFFFFF',kind(i)) /= -1) call abort
+
+ if (popcnt(int(z'0F00F00080000001',8)) /= 10) call abort
+ if (popcnt(int(z'800F0001',4)) /= 6) call abort
+
+end program test
diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c
index df6923f76ef..9c175de4e9d 100644
--- a/gcc/tree-nested.c
+++ b/gcc/tree-nested.c
@@ -1082,6 +1082,11 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
need_stmts = true;
goto do_decl_clause;
+ case OMP_CLAUSE_LINEAR:
+ if (OMP_CLAUSE_LINEAR_GIMPLE_SEQ (clause))
+ need_stmts = true;
+ goto do_decl_clause;
+
case OMP_CLAUSE_PRIVATE:
case OMP_CLAUSE_FIRSTPRIVATE:
case OMP_CLAUSE_COPYPRIVATE:
@@ -1157,6 +1162,12 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (clause));
break;
+ case OMP_CLAUSE_LINEAR:
+ walk_body (convert_nonlocal_reference_stmt,
+ convert_nonlocal_reference_op, info,
+ &OMP_CLAUSE_LINEAR_GIMPLE_SEQ (clause));
+ break;
+
default:
break;
}
@@ -1605,6 +1616,11 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
need_stmts = true;
goto do_decl_clause;
+ case OMP_CLAUSE_LINEAR:
+ if (OMP_CLAUSE_LINEAR_GIMPLE_SEQ (clause))
+ need_stmts = true;
+ goto do_decl_clause;
+
case OMP_CLAUSE_PRIVATE:
case OMP_CLAUSE_FIRSTPRIVATE:
case OMP_CLAUSE_COPYPRIVATE:
@@ -1685,6 +1701,12 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (clause));
break;
+ case OMP_CLAUSE_LINEAR:
+ walk_body (convert_local_reference_stmt,
+ convert_local_reference_op, info,
+ &OMP_CLAUSE_LINEAR_GIMPLE_SEQ (clause));
+ break;
+
default:
break;
}
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index 46dc00c38a3..0d941019f0e 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -586,7 +586,7 @@ extern gimple_opt_pass *make_pass_convert_switch (gcc::context *ctxt);
extern opt_pass *current_pass;
extern bool execute_one_pass (opt_pass *);
-extern void execute_pass_list (opt_pass *);
+extern void execute_pass_list (function *, opt_pass *);
extern void execute_ipa_pass_list (opt_pass *);
extern void execute_ipa_summary_passes (ipa_opt_pass_d *);
extern void execute_all_ipa_transforms (void);
@@ -614,7 +614,7 @@ extern bool function_called_by_processed_nodes_p (void);
extern bool first_pass_instance;
/* Declare for plugins. */
-extern void do_per_function_toporder (void (*) (void *), void *);
+extern void do_per_function_toporder (void (*) (function *, void *), void *);
extern void disable_pass (const char *);
extern void enable_pass (const char *);
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index e040c4fc58d..5074142f6f2 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -7243,10 +7243,7 @@ ipa_pta_execute (void)
tree ptr;
struct function *fn;
unsigned i;
- varinfo_t fi;
basic_block bb;
- struct pt_solution uses, clobbers;
- struct cgraph_edge *e;
/* Nodes without a body are not interesting. */
if (!cgraph_function_with_gimple_body_p (node) || node->clone_of)
@@ -7262,21 +7259,6 @@ ipa_pta_execute (void)
find_what_p_points_to (ptr);
}
- /* Compute the call-use and call-clobber sets for all direct calls. */
- fi = lookup_vi_for_tree (node->decl);
- gcc_assert (fi->is_fn_info);
- clobbers
- = find_what_var_points_to (first_vi_for_offset (fi, fi_clobbers));
- uses = find_what_var_points_to (first_vi_for_offset (fi, fi_uses));
- for (e = node->callers; e; e = e->next_caller)
- {
- if (!e->call_stmt)
- continue;
-
- *gimple_call_clobber_set (e->call_stmt) = clobbers;
- *gimple_call_use_set (e->call_stmt) = uses;
- }
-
/* Compute the call-use and call-clobber sets for indirect calls
and calls to external functions. */
FOR_EACH_BB_FN (bb, fn)
@@ -7287,17 +7269,27 @@ ipa_pta_execute (void)
{
gimple stmt = gsi_stmt (gsi);
struct pt_solution *pt;
- varinfo_t vi;
+ varinfo_t vi, fi;
tree decl;
if (!is_gimple_call (stmt))
continue;
- /* Handle direct calls to external functions. */
+ /* Handle direct calls to functions with body. */
decl = gimple_call_fndecl (stmt);
if (decl
- && (!(fi = lookup_vi_for_tree (decl))
- || !fi->is_fn_info))
+ && (fi = lookup_vi_for_tree (decl))
+ && fi->is_fn_info)
+ {
+ *gimple_call_clobber_set (stmt)
+ = find_what_var_points_to
+ (first_vi_for_offset (fi, fi_clobbers));
+ *gimple_call_use_set (stmt)
+ = find_what_var_points_to
+ (first_vi_for_offset (fi, fi_uses));
+ }
+ /* Handle direct calls to external functions. */
+ else if (decl)
{
pt = gimple_call_use_set (stmt);
if (gimple_call_flags (stmt) & ECF_CONST)
@@ -7341,10 +7333,9 @@ ipa_pta_execute (void)
pt->nonlocal = 1;
}
}
-
/* Handle indirect calls. */
- if (!decl
- && (fi = get_fi_for_callee (stmt)))
+ else if (!decl
+ && (fi = get_fi_for_callee (stmt)))
{
/* We need to accumulate all clobbers/uses of all possible
callees. */
diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
index 8a0103b1637..7621348944f 100644
--- a/gcc/tree-ssa-threadedge.c
+++ b/gcc/tree-ssa-threadedge.c
@@ -398,7 +398,7 @@ record_temporary_equivalences_from_stmts_at_dest (edge e,
ssa_op_iter iter;
if (backedge_seen)
- FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_ALL_DEFS)
+ FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_DEF)
{
/* This call only invalidates equivalences created by
PHI nodes. This is by design to keep the cost of
diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c
index 9ac111772f4..e22ce2cc71d 100644
--- a/gcc/tree-vect-generic.c
+++ b/gcc/tree-vect-generic.c
@@ -969,7 +969,8 @@ expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type
if (!optimize
|| !VECTOR_INTEGER_TYPE_P (type)
- || TREE_CODE (rhs2) != VECTOR_CST)
+ || TREE_CODE (rhs2) != VECTOR_CST
+ || !VECTOR_MODE_P (TYPE_MODE (type)))
break;
ret = expand_vector_divmod (gsi, type, rhs1, rhs2, code);
diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
index 75116177fed..094cf047e05 100644
--- a/gcc/tree-vect-patterns.c
+++ b/gcc/tree-vect-patterns.c
@@ -392,6 +392,8 @@ vect_recog_dot_prod_pattern (vec<gimple> *stmts, tree *type_in,
gcc_assert (STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_internal_def);
oprnd00 = gimple_assign_rhs1 (stmt);
oprnd01 = gimple_assign_rhs2 (stmt);
+ STMT_VINFO_PATTERN_DEF_SEQ (vinfo_for_stmt (last_stmt))
+ = STMT_VINFO_PATTERN_DEF_SEQ (stmt_vinfo);
}
else
{
@@ -3065,8 +3067,7 @@ vect_mark_pattern_stmts (gimple orig_stmt, gimple pattern_stmt,
}
gimple_set_bb (def_stmt, gimple_bb (orig_stmt));
STMT_VINFO_RELATED_STMT (def_stmt_info) = orig_stmt;
- STMT_VINFO_DEF_TYPE (def_stmt_info)
- = STMT_VINFO_DEF_TYPE (orig_stmt_info);
+ STMT_VINFO_DEF_TYPE (def_stmt_info) = vect_internal_def;
if (STMT_VINFO_VECTYPE (def_stmt_info) == NULL_TREE)
STMT_VINFO_VECTYPE (def_stmt_info) = pattern_vectype;
}
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 2e2a27f874f..7951805e473 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -3949,52 +3949,6 @@ adjust_range_with_scev (value_range_t *vr, struct loop *loop,
}
}
-/* Return true if VAR may overflow at STMT. This checks any available
- loop information to see if we can determine that VAR does not
- overflow. */
-
-static bool
-vrp_var_may_overflow (tree var, gimple stmt)
-{
- struct loop *l;
- tree chrec, init, step;
-
- if (current_loops == NULL)
- return true;
-
- l = loop_containing_stmt (stmt);
- if (l == NULL
- || !loop_outer (l))
- return true;
-
- chrec = instantiate_parameters (l, analyze_scalar_evolution (l, var));
- if (TREE_CODE (chrec) != POLYNOMIAL_CHREC)
- return true;
-
- init = initial_condition_in_loop_num (chrec, l->num);
- step = evolution_part_in_loop_num (chrec, l->num);
-
- if (step == NULL_TREE
- || !is_gimple_min_invariant (step)
- || !valid_value_p (init))
- return true;
-
- /* If we get here, we know something useful about VAR based on the
- loop information. If it wraps, it may overflow. */
-
- if (scev_probably_wraps_p (init, step, stmt, get_chrec_loop (chrec),
- true))
- return true;
-
- if (dump_file && (dump_flags & TDF_DETAILS) != 0)
- {
- print_generic_expr (dump_file, var, 0);
- fprintf (dump_file, ": loop information indicates does not overflow\n");
- }
-
- return false;
-}
-
/* Given two numeric value ranges VR0, VR1 and a comparison code COMP:
@@ -8382,32 +8336,32 @@ vrp_visit_phi_node (gimple phi)
&& (cmp_min != 0 || cmp_max != 0))
goto varying;
- /* If the new minimum is smaller or larger than the previous
- one, go all the way to -INF. In the first case, to avoid
- iterating millions of times to reach -INF, and in the
- other case to avoid infinite bouncing between different
- minimums. */
- if (cmp_min > 0 || cmp_min < 0)
- {
- if (!needs_overflow_infinity (TREE_TYPE (vr_result.min))
- || !vrp_var_may_overflow (lhs, phi))
- vr_result.min = TYPE_MIN_VALUE (TREE_TYPE (vr_result.min));
- else if (supports_overflow_infinity (TREE_TYPE (vr_result.min)))
- vr_result.min =
- negative_overflow_infinity (TREE_TYPE (vr_result.min));
- }
-
- /* Similarly, if the new maximum is smaller or larger than
- the previous one, go all the way to +INF. */
- if (cmp_max < 0 || cmp_max > 0)
- {
- if (!needs_overflow_infinity (TREE_TYPE (vr_result.max))
- || !vrp_var_may_overflow (lhs, phi))
- vr_result.max = TYPE_MAX_VALUE (TREE_TYPE (vr_result.max));
- else if (supports_overflow_infinity (TREE_TYPE (vr_result.max)))
- vr_result.max =
- positive_overflow_infinity (TREE_TYPE (vr_result.max));
- }
+ /* If the new minimum is larger than than the previous one
+ retain the old value. If the new minimum value is smaller
+ than the previous one and not -INF go all the way to -INF + 1.
+ In the first case, to avoid infinite bouncing between different
+ minimums, and in the other case to avoid iterating millions of
+ times to reach -INF. Going to -INF + 1 also lets the following
+ iteration compute whether there will be any overflow, at the
+ expense of one additional iteration. */
+ if (cmp_min < 0)
+ vr_result.min = lhs_vr->min;
+ else if (cmp_min > 0
+ && !vrp_val_is_min (vr_result.min))
+ vr_result.min
+ = int_const_binop (PLUS_EXPR,
+ vrp_val_min (TREE_TYPE (vr_result.min)),
+ build_int_cst (TREE_TYPE (vr_result.min), 1));
+
+ /* Similarly for the maximum value. */
+ if (cmp_max > 0)
+ vr_result.max = lhs_vr->max;
+ else if (cmp_max < 0
+ && !vrp_val_is_max (vr_result.max))
+ vr_result.max
+ = int_const_binop (MINUS_EXPR,
+ vrp_val_max (TREE_TYPE (vr_result.min)),
+ build_int_cst (TREE_TYPE (vr_result.min), 1));
/* If we dropped either bound to +-INF then if this is a loop
PHI node SCEV may known more about its value-range. */
diff --git a/gcc/tree.h b/gcc/tree.h
index 57c952802a8..3e8e625ab9f 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1333,6 +1333,9 @@ extern void protected_set_expr_location (tree, location_t);
#define OMP_CLAUSE_LINEAR_STEP(NODE) \
OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_LINEAR), 1)
+#define OMP_CLAUSE_LINEAR_GIMPLE_SEQ(NODE) \
+ (OMP_CLAUSE_CHECK (NODE))->omp_clause.gimple_reduction_init
+
#define OMP_CLAUSE_ALIGNED_ALIGNMENT(NODE) \
OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ALIGNED), 1)