diff options
author | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-01-19 10:29:54 +0000 |
---|---|---|
committer | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-01-19 10:29:54 +0000 |
commit | 5b9a94504088e7452ea562233e9643e0d8205df6 (patch) | |
tree | fc86c19aa122e91770ae23801d19b8a249fe74d7 /gcc | |
parent | 01c7add04011110f55f1f7b662ab1b8dc99ed9d4 (diff) | |
download | gcc-5b9a94504088e7452ea562233e9643e0d8205df6.tar.gz |
2011-01-19 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk rev 168984
2011-01-19 Basile Starynkevitch <basile@starynkevitch.net>
* gcc/melt/warmelt-outobj.melt (generate_runtypesupport_mapfun):
Correct some typos in generated code.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@168988 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
77 files changed, 2799 insertions, 1195 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 105d5a41cdb..c456fb34f5b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,264 @@ +2011-01-19 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/47290 + * tree-eh.c (infinite_empty_loop_p): New function. + (cleanup_empty_eh): Use it. + +2011-01-18 Steve Ellcey <sje@cup.hp.com> + + PR target/46997 + * ia64.c (ia64_expand_unpack): Fix code for TARGET_BIG_ENDIAN. + (a64_expand_widen_sum): Ditto. + * vect.md (mulv2si3): Disable for TARGET_BIG_ENDIAN. + (vec_extract_evenodd_help): Ditto. + (vec_extract_evenv4hi): Ditto. + (vec_extract_oddv4hi): Ditto. + (vec_extract_evenv2si): Ditto. + (vec_extract_oddv2si): Ditto. + (vec_extract_evenv2sf): Ditto. + (vec_extract_oddv2sf): Ditto. + (vec_pack_trunc_v4hi: Ditto. + (vec_pack_trunc_v2si): Ditto. + (vec_interleave_lowv8qi): Fix for TARGET_BIG_ENDIAN. + (vec_interleave_highv8qi): Ditto. + (mix1_r): Ditto. + (vec_extract_oddv8qi): Ditto. + (vec_interleave_lowv4hi): Ditto. + (vec_interleave_highv4hi): Ditto. + (vec_interleave_lowv2si): Ditto. + (vec_interleave_highv2si): Ditto. + +2011-01-18 John David Anglin <dave.anglin@nrc-cnrc.gc.ca> + + * doc/extend.texi: Mention __float128 support on hppa HP-UX. + * config/pa/pa-hpux.h (HPUX_LONG_DOUBLE_LIBRARY): Define to 1. + * config/pa/pa.c (pa_expand_builtin): New. Include "langhooks.h". + (pa_c_mode_for_suffix): New. + (TARGET_EXPAND_BUILTIN): Define. + (TARGET_C_MODE_FOR_SUFFIX): Define. + (pa_builtins): Define. + (pa_init_builtins): Register __float128 type and init new support + builtins. + * config/pa/pa.h (HPUX_LONG_DOUBLE_LIBRARY): Define if not defined. + * config/pa/quadlib.c (_U_Qfcopysign): New. + +2011-01-18 Eric Botcazou <ebotcazou@adacore.com> + + PR middle-end/46894 + * explow.c (allocate_dynamic_stack_space): Do not assume more than + BITS_PER_UNIT alignment if STACK_DYNAMIC_OFFSET or STACK_POINTER_OFFSET + are defined. + +2011-01-18 Ulrich Weigand <Ulrich.Weigand@de.ibm.com> + + PR tree-optimization/47179 + * config/spu/spu.c (spu_ref_may_alias_errno): New function. + (TARGET_REF_MAY_ALIAS_ERRNO): Define. + +2011-01-18 Richard Guenther <rguenther@suse.de> + + PR rtl-optimization/47216 + * emit-rtl.c: Include tree-flow.h. + (set_mem_attributes_minus_bitpos): Use tree_could_trap_p instead + of replicating it with different semantics. + * Makefile.in (emit-rtl.o): Adjust. + +2011-01-18 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com> + + * config/arm/cortex-a9.md (cortex-a9-neon.md): Actually + include. + (cortex_a9_dp): Handle neon types correctly. + +2011-01-18 Jakub Jelinek <jakub@redhat.com> + + PR rtl-optimization/47299 + * expr.c (expand_expr_real_2) <case WIDEN_MULT_EXPR>: Don't use + subtarget. Use normal multiplication if both operands are + constants. + * expmed.c (expand_widening_mult): Don't try to optimize constant + multiplication if op0 has VOIDmode. Convert op1 constant to mode + before using it. + +2011-01-17 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> + + * doc/lto.texi (LTO): Ensure two spaces after period. Fix + spacing after 'e.g.', typos, comma, hyphenation. + +2011-01-17 Richard Henderson <rth@redhat.com> + + * config/rx/predicates.md (rx_constshift_operand): Use match_test. + (rx_restricted_mem_operand): New. + (rx_shift_operand): Use register_operand. + (rx_source_operand, rx_compare_operand): Likewise. + * config/rx/rx.md (addsi3_flags): New expander. + (adddi3): Rewrite as expander. + (adc_internal, *adc_flags, adddi3_internal): New patterns. + (subsi3_flags): New expander. + (subdi3): Rewrite as expander. + (sbb_internal, *sbb_flags, subdi3_internal): New patterns. + + * config/rx/rx.c (RX_BUILTIN_SAT): Remove. + (rx_init_builtins): Remove sat builtin. + (rx_expand_builtin): Likewise. + * config/rx/rx.md (ssaddsi3): New. + (*sat): Rename from sat. Represent the CC_REG input. + + * config/rx/predicates.md (rshift_operator): New. + * config/rx/rx.c (rx_expand_insv): Remove. + * config/rx/rx-protos.h: Update. + * config/rx/rx.md (*bitset): Rename from bitset. Swap the ashift + operand to the canonical position. + (*bitset_in_memory, *bitinvert, *bitinvert_in_memory): Similarly. + (*bitclr, *bitclr_in_memory): Similarly. + (*insv_imm, rx_insv_reg, *insv_cond, *bmcc, *insv_cond_lt): New. + (insv): Retain the zero_extract in the expansion. + + * config/rx/rx.md (bswapsi2): Use = not + for output reload. + (bswaphi2, bitinvert, revw): Likewise. + + * config/rx/rx.c (gen_rx_store_vector): Use VOIDmode for gen_rtx_SET. + (gen_rx_rtsd_vector, gen_rx_popm_vector): Likewise. + * config/rx/rx.md (pop_and_return): Use VOIDmode for SET. + (stack_push, stack_pushm, stack_pop, stack_popm): Likewise. + (bitset, bitset_in_memory): Likewise. + (bitinvert, bitinvert_in_memory): Likewise. + (bitclr, bitclr_in_memory): Likewise. + (insv, sync_lock_test_and_setsi, movstr, rx_movstr): Likewise. + (rx_strend, rx_cmpstrn): Likewise. + (rx_setmem): Likewise. Make the source BLKmode to match the dest. + (bitop peep2 patterns): Remove. + + * config/rx/rx.c (rx_match_ccmode): New. + * config/rx/rx-protos.h: Update. + * config/rx/rx.md (abssi2): Clobber, don't set flags. + (addsi3, adddi3, andsi3, negsi2, one_cmplsi2, iorsi3): Likewise. + (rotlsi3, rotrsi3, ashrsi3, lshrsi3, ashlsi3): Likewise. + (subsi3, subdi3, xorsi3, addsf3, divsf3, mulsf3, subsf3): Likewise. + (fix_truncsfsi2, floatsisf2): Likewise. + (*abssi2_flags, *addsi3_flags, *andsi3_flags, *negsi2_flags): New. + (*one_cmplsi2_flags, *iorsi3_flags, *rotlsi3_flags): New. + (*rotrsi3_flags, *ashrsi3_flags, *lshrsi3_flags, *ashlsi3_flags): New. + (*subsi3_flags, *xorsi3_flags): New. + + * config/rx/rx.md (cstoresf4, *cstoresf4): New patterns. + + * config/rx/rx.c (rx_print_operand): Remove workaround for + unsplit comparison operations. + + * config/rx/rx.md (movsicc): Split after reload. + (*movsicc): Merge *movsieq and *movsine via match_operator. + (*stcc): New pattern. + + * config/rx/rx.c (rx_float_compare_mode): Remove. + * config/rx/rx.h (rx_float_compare_mode): Remove. + * config/rx/rx.md (cstoresi4): Split after reload. + (*sccc): New pattern. + + * config/rx/predicates.md (label_ref_operand): New. + (rx_z_comparison_operator): New. + (rx_zs_comparison_operator): New. + (rx_fp_comparison_operator): New. + * config/rx/rx.c (rx_print_operand) [B]: Examine comparison modes. + Validate that the flags are set properly for the comparison. + (rx_gen_cond_branch_template): Remove. + (rx_cc_modes_compatible): Remove. + (mode_from_flags): New. + (flags_from_code): Rename from flags_needed_for_conditional. + (rx_cc_modes_compatible): Re-write in terms of flags_from_mode. + (rx_select_cc_mode): Likewise. + (rx_split_fp_compare): New. + (rx_split_cbranch): New. + * config/rx/rx.md (most_cond, zs_cond): Remove iterators. + (*cbranchsi4): Use match_operator and rx_split_cbranch. + (*cbranchsf4): Similarly. + (*cbranchsi4_tst): Rename from *tstbranchsi4_<code>. Use + match_operator and rx_split_cbranch. + (*cbranchsi4_tst_ext): Combine *tstbranchsi4m_eq and + tstbranchsi4m_ne. Use match_operator and rx_split_cbranch. + (*cmpsi): Rename from cmpsi. + (*tstsi): Rename from tstsi. + (*cmpsf): Rename from cmpsf; use CC_Fmode. + (*conditional_branch): Rename from conditional_branch. + (*reveresed_conditional_branch): Remove. + (b<code>): Remove expander. + * config/rx/rx-protos.h: Update. + + * config/rx/rx.c (rx_compare_redundant): Remove. + * config/rx/rx.md (cmpsi): Don't use it. + * config/rx/rx-protos.h: Update. + + * config/rx/rx-modes.def (CC_F): New mode. + * config/rx/rx.c (rx_select_cc_mode): New. + * config/rx/rx.h (SELECT_CC_MODE): Use it. + * config/rx/rx-protos.h: Update. + +2011-01-17 Richard Henderson <rth@redhat.com> + + * except.c (dump_eh_tree): Fix stray ; after for statement. + +2011-01-17 Richard Guenther <rguenther@suse.de> + + PR tree-optimization/47313 + * tree-inline.c (tree_function_versioning): Move DECL_RESULT + handling before copying the body. Properly deal with + by-reference result in SSA form. + +2011-01-17 Ian Lance Taylor <iant@google.com> + + PR target/47219 + * config/sparc/sparc.c (sparc_sr_alias_set): Don't define. + (struct_value_alias_set): Don't define. + (sparc_option_override): Don't set sparc_sr_alias_set and + struct_value_alias_set. + (save_or_restore_regs): Use gen_frame_mem rather than calling + set_mem_alias_set. + (sparc_struct_value_rtx): Likewise. + +2011-01-17 H.J. Lu <hongjiu.lu@intel.com> + + PR target/47318 + * config/i386/avxintrin.h (_mm_maskload_pd): Change mask to + __m128i. + (_mm_maskstore_pd): Likewise. + (_mm_maskload_ps): Likewise. + (_mm_maskstore_ps): Likewise. + (_mm256_maskload_pd): Change mask to __m256i. + (_mm256_maskstore_pd): Likewise. + (_mm256_maskload_ps): Likewise. + (_mm256_maskstore_ps): Likewise. + + * config/i386/i386-builtin-types.def: Updated. + (ix86_expand_special_args_builtin): Likewise. + + * config/i386/i386.c (bdesc_special_args): Update + __builtin_ia32_maskloadpd, __builtin_ia32_maskloadps, + __builtin_ia32_maskloadpd256, __builtin_ia32_maskloadps256, + __builtin_ia32_maskstorepd, __builtin_ia32_maskstoreps, + __builtin_ia32_maskstorepd256 and __builtin_ia32_maskstoreps256. + + * config/i386/sse.md (avx_maskload<ssemodesuffix><avxmodesuffix>): + Use <avxpermvecmode> on mask register. + (avx_maskstore<ssemodesuffix><avxmodesuffix>): Likewise. + +2011-01-17 Olivier Hainque <hainque@adacore.com> + Michael Haubenwallner <michael.haubenwallner@salomon.at> + Eric Botcazou <ebotcazou@adacore.com> + + PR target/46655 + * xcoffout.c (ASM_OUTPUT_LINE): Output line only if positive, and only + if <= USHRT_MAX in 32-bit mode. + +2011-01-17 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> + + * doc/install.texi (Configuration, Specific): Wrap long + lines in examples. Allow line wrapping in long options + and URLs where beneficial for PDF output. + +2011-01-16 Richard Sandiford <rdsandiford@googlemail.com> + + * config/mips/mips.c (mips_classify_symbol): Don't return + SYMBOL_PC_RELATIVE for nonlocal labels. + 2011-01-15 Eric Botcazou <ebotcazou@adacore.com> * config/sparc/sol2-bi.h (CC1_SPEC): Fix typo. diff --git a/gcc/ChangeLog.MELT b/gcc/ChangeLog.MELT index 0317650fcf4..48bdafa2c33 100644 --- a/gcc/ChangeLog.MELT +++ b/gcc/ChangeLog.MELT @@ -1,6 +1,11 @@ 2011-01-19 Basile Starynkevitch <basile@starynkevitch.net> + * melt/warmelt-outobj.melt (generate_runtypesupport_mapfun): + Correct some typos in generated code. + +2011-01-19 Basile Starynkevitch <basile@starynkevitch.net> + * melt/warmelt-base.melt (some_string_value): New cmatcher. * melt/warmelt-outobj.melt (generate_runtypesupport_mapfun): Adding diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 8b280586408..3972b782259 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20110116 +20110119 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 12168ee925d..b6436290868 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -3011,7 +3011,7 @@ emit-rtl.o : emit-rtl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(TREE_H) $(FLAGS_H) $(FUNCTION_H) $(REGS_H) insn-config.h $(RECOG_H) \ $(GGC_H) $(EXPR_H) hard-reg-set.h $(BITMAP_H) $(DIAGNOSTIC_CORE_H) $(BASIC_BLOCK_H) \ $(HASHTAB_H) $(TM_P_H) debug.h langhooks.h $(TREE_PASS_H) gt-emit-rtl.h \ - $(DF_H) $(PARAMS_H) $(TARGET_H) + $(DF_H) $(PARAMS_H) $(TARGET_H) $(TREE_FLOW_H) real.o : real.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \ $(DIAGNOSTIC_CORE_H) $(TM_P_H) $(REAL_H) dfp.h realmpfr.h realmpfr.o : realmpfr.c realmpfr.h $(CONFIG_H) $(SYSTEM_H) $(REAL_H) diff --git a/gcc/config/arm/cortex-a9.md b/gcc/config/arm/cortex-a9.md index 8c336675b21..b74ace8332a 100644 --- a/gcc/config/arm/cortex-a9.md +++ b/gcc/config/arm/cortex-a9.md @@ -79,10 +79,11 @@ cortex_a9_p1_e2 + cortex_a9_p0_e1 + cortex_a9_p1_e1") ;; which can go down E2 without any problem. (define_insn_reservation "cortex_a9_dp" 2 (and (eq_attr "tune" "cortexa9") - (ior (eq_attr "type" "alu") - (ior (and (eq_attr "type" "alu_shift_reg, alu_shift") - (eq_attr "insn" "mov")) - (eq_attr "neon_type" "none")))) + (ior (and (eq_attr "type" "alu") + (eq_attr "neon_type" "none")) + (and (and (eq_attr "type" "alu_shift_reg, alu_shift") + (eq_attr "insn" "mov")) + (eq_attr "neon_type" "none")))) "cortex_a9_p0_default|cortex_a9_p1_default") ;; An instruction using the shifter will go down E1. @@ -263,3 +264,6 @@ cortex_a9_store3_4, cortex_a9_store1_2, cortex_a9_load3_4") (and (eq_attr "tune" "cortexa9") (eq_attr "type" "fdivd")) "ca9fp_ds1 + ca9_issue_vfp_neon, nothing*24") + +;; Include Neon pipeline description +(include "cortex-a9-neon.md") diff --git a/gcc/config/i386/avxintrin.h b/gcc/config/i386/avxintrin.h index 26925fd7fbb..70bfce1a274 100644 --- a/gcc/config/i386/avxintrin.h +++ b/gcc/config/i386/avxintrin.h @@ -890,55 +890,55 @@ _mm256_storeu_si256 (__m256i *__P, __m256i __A) } extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) -_mm_maskload_pd (double const *__P, __m128d __M) +_mm_maskload_pd (double const *__P, __m128i __M) { return (__m128d) __builtin_ia32_maskloadpd ((const __v2df *)__P, - (__v2df)__M); + (__v2di)__M); } extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) -_mm_maskstore_pd (double *__P, __m128d __M, __m128d __A) +_mm_maskstore_pd (double *__P, __m128i __M, __m128d __A) { - __builtin_ia32_maskstorepd ((__v2df *)__P, (__v2df)__M, (__v2df)__A); + __builtin_ia32_maskstorepd ((__v2df *)__P, (__v2di)__M, (__v2df)__A); } extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) -_mm256_maskload_pd (double const *__P, __m256d __M) +_mm256_maskload_pd (double const *__P, __m256i __M) { return (__m256d) __builtin_ia32_maskloadpd256 ((const __v4df *)__P, - (__v4df)__M); + (__v4di)__M); } extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) -_mm256_maskstore_pd (double *__P, __m256d __M, __m256d __A) +_mm256_maskstore_pd (double *__P, __m256i __M, __m256d __A) { - __builtin_ia32_maskstorepd256 ((__v4df *)__P, (__v4df)__M, (__v4df)__A); + __builtin_ia32_maskstorepd256 ((__v4df *)__P, (__v4di)__M, (__v4df)__A); } extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) -_mm_maskload_ps (float const *__P, __m128 __M) +_mm_maskload_ps (float const *__P, __m128i __M) { return (__m128) __builtin_ia32_maskloadps ((const __v4sf *)__P, - (__v4sf)__M); + (__v4si)__M); } extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) -_mm_maskstore_ps (float *__P, __m128 __M, __m128 __A) +_mm_maskstore_ps (float *__P, __m128i __M, __m128 __A) { - __builtin_ia32_maskstoreps ((__v4sf *)__P, (__v4sf)__M, (__v4sf)__A); + __builtin_ia32_maskstoreps ((__v4sf *)__P, (__v4si)__M, (__v4sf)__A); } extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) -_mm256_maskload_ps (float const *__P, __m256 __M) +_mm256_maskload_ps (float const *__P, __m256i __M) { return (__m256) __builtin_ia32_maskloadps256 ((const __v8sf *)__P, - (__v8sf)__M); + (__v8si)__M); } extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) -_mm256_maskstore_ps (float *__P, __m256 __M, __m256 __A) +_mm256_maskstore_ps (float *__P, __m256i __M, __m256 __A) { - __builtin_ia32_maskstoreps256 ((__v8sf *)__P, (__v8sf)__M, (__v8sf)__A); + __builtin_ia32_maskstoreps256 ((__v8sf *)__P, (__v8si)__M, (__v8sf)__A); } extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) diff --git a/gcc/config/i386/i386-builtin-types.def b/gcc/config/i386/i386-builtin-types.def index 079c8ec3659..05a7f546803 100644 --- a/gcc/config/i386/i386-builtin-types.def +++ b/gcc/config/i386/i386-builtin-types.def @@ -236,7 +236,7 @@ DEF_FUNCTION_TYPE (V1DI, V1DI, SI) DEF_FUNCTION_TYPE (V1DI, V1DI, V1DI) DEF_FUNCTION_TYPE (V1DI, V2SI, V2SI) DEF_FUNCTION_TYPE (V1DI, V8QI, V8QI) -DEF_FUNCTION_TYPE (V2DF, PCV2DF, V2DF) +DEF_FUNCTION_TYPE (V2DF, PCV2DF, V2DI) DEF_FUNCTION_TYPE (V2DF, V2DF, DI) DEF_FUNCTION_TYPE (V2DF, V2DF, INT) DEF_FUNCTION_TYPE (V2DF, V2DF, PCDOUBLE) @@ -258,7 +258,7 @@ DEF_FUNCTION_TYPE (V2SI, V2SF, V2SF) DEF_FUNCTION_TYPE (V2SI, V2SI, SI) DEF_FUNCTION_TYPE (V2SI, V2SI, V2SI) DEF_FUNCTION_TYPE (V2SI, V4HI, V4HI) -DEF_FUNCTION_TYPE (V4DF, PCV4DF, V4DF) +DEF_FUNCTION_TYPE (V4DF, PCV4DF, V4DI) DEF_FUNCTION_TYPE (V4DF, V4DF, INT) DEF_FUNCTION_TYPE (V4DF, V4DF, V4DF) DEF_FUNCTION_TYPE (V4DF, V4DF, V4DI) @@ -267,7 +267,7 @@ DEF_FUNCTION_TYPE (V4HI, V4HI, INT) DEF_FUNCTION_TYPE (V4HI, V4HI, SI) DEF_FUNCTION_TYPE (V4HI, V4HI, V4HI) DEF_FUNCTION_TYPE (V4HI, V8QI, V8QI) -DEF_FUNCTION_TYPE (V4SF, PCV4SF, V4SF) +DEF_FUNCTION_TYPE (V4SF, PCV4SF, V4SI) DEF_FUNCTION_TYPE (V4SF, V4SF, DI) DEF_FUNCTION_TYPE (V4SF, V4SF, INT) DEF_FUNCTION_TYPE (V4SF, V4SF, PCV2SF) @@ -293,7 +293,7 @@ DEF_FUNCTION_TYPE (V8HI, V8SF, INT) DEF_FUNCTION_TYPE (V8HI, V4SF, INT) DEF_FUNCTION_TYPE (V8QI, V4HI, V4HI) DEF_FUNCTION_TYPE (V8QI, V8QI, V8QI) -DEF_FUNCTION_TYPE (V8SF, PCV8SF, V8SF) +DEF_FUNCTION_TYPE (V8SF, PCV8SF, V8SI) DEF_FUNCTION_TYPE (V8SF, V8SF, INT) DEF_FUNCTION_TYPE (V8SF, V8SF, V8SF) DEF_FUNCTION_TYPE (V8SF, V8SF, V8SI) @@ -352,10 +352,10 @@ DEF_FUNCTION_TYPE (V8SI, V8SI, V4SI, INT) DEF_FUNCTION_TYPE (V8SI, V8SI, V8SI, INT) DEF_FUNCTION_TYPE (V8SI, V8SI, V8SI, V8SI) DEF_FUNCTION_TYPE (VOID, PCVOID, UNSIGNED, UNSIGNED) -DEF_FUNCTION_TYPE (VOID, PV2DF, V2DF, V2DF) -DEF_FUNCTION_TYPE (VOID, PV4DF, V4DF, V4DF) -DEF_FUNCTION_TYPE (VOID, PV4SF, V4SF, V4SF) -DEF_FUNCTION_TYPE (VOID, PV8SF, V8SF, V8SF) +DEF_FUNCTION_TYPE (VOID, PV2DF, V2DI, V2DF) +DEF_FUNCTION_TYPE (VOID, PV4DF, V4DI, V4DF) +DEF_FUNCTION_TYPE (VOID, PV4SF, V4SI, V4SF) +DEF_FUNCTION_TYPE (VOID, PV8SF, V8SI, V8SF) DEF_FUNCTION_TYPE (VOID, UINT, UINT, UINT) DEF_FUNCTION_TYPE (VOID, UINT64, UINT, UINT) DEF_FUNCTION_TYPE (VOID, V16QI, V16QI, PCHAR) diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index a26314b0bba..f5843dea9e4 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -24483,14 +24483,14 @@ static const struct builtin_description bdesc_special_args[] = { OPTION_MASK_ISA_AVX, CODE_FOR_avx_movntv4df, "__builtin_ia32_movntpd256", IX86_BUILTIN_MOVNTPD256, UNKNOWN, (int) VOID_FTYPE_PDOUBLE_V4DF }, { OPTION_MASK_ISA_AVX, CODE_FOR_avx_movntv8sf, "__builtin_ia32_movntps256", IX86_BUILTIN_MOVNTPS256, UNKNOWN, (int) VOID_FTYPE_PFLOAT_V8SF }, - { OPTION_MASK_ISA_AVX, CODE_FOR_avx_maskloadpd, "__builtin_ia32_maskloadpd", IX86_BUILTIN_MASKLOADPD, UNKNOWN, (int) V2DF_FTYPE_PCV2DF_V2DF }, - { OPTION_MASK_ISA_AVX, CODE_FOR_avx_maskloadps, "__builtin_ia32_maskloadps", IX86_BUILTIN_MASKLOADPS, UNKNOWN, (int) V4SF_FTYPE_PCV4SF_V4SF }, - { OPTION_MASK_ISA_AVX, CODE_FOR_avx_maskloadpd256, "__builtin_ia32_maskloadpd256", IX86_BUILTIN_MASKLOADPD256, UNKNOWN, (int) V4DF_FTYPE_PCV4DF_V4DF }, - { OPTION_MASK_ISA_AVX, CODE_FOR_avx_maskloadps256, "__builtin_ia32_maskloadps256", IX86_BUILTIN_MASKLOADPS256, UNKNOWN, (int) V8SF_FTYPE_PCV8SF_V8SF }, - { OPTION_MASK_ISA_AVX, CODE_FOR_avx_maskstorepd, "__builtin_ia32_maskstorepd", IX86_BUILTIN_MASKSTOREPD, UNKNOWN, (int) VOID_FTYPE_PV2DF_V2DF_V2DF }, - { OPTION_MASK_ISA_AVX, CODE_FOR_avx_maskstoreps, "__builtin_ia32_maskstoreps", IX86_BUILTIN_MASKSTOREPS, UNKNOWN, (int) VOID_FTYPE_PV4SF_V4SF_V4SF }, - { OPTION_MASK_ISA_AVX, CODE_FOR_avx_maskstorepd256, "__builtin_ia32_maskstorepd256", IX86_BUILTIN_MASKSTOREPD256, UNKNOWN, (int) VOID_FTYPE_PV4DF_V4DF_V4DF }, - { OPTION_MASK_ISA_AVX, CODE_FOR_avx_maskstoreps256, "__builtin_ia32_maskstoreps256", IX86_BUILTIN_MASKSTOREPS256, UNKNOWN, (int) VOID_FTYPE_PV8SF_V8SF_V8SF }, + { OPTION_MASK_ISA_AVX, CODE_FOR_avx_maskloadpd, "__builtin_ia32_maskloadpd", IX86_BUILTIN_MASKLOADPD, UNKNOWN, (int) V2DF_FTYPE_PCV2DF_V2DI }, + { OPTION_MASK_ISA_AVX, CODE_FOR_avx_maskloadps, "__builtin_ia32_maskloadps", IX86_BUILTIN_MASKLOADPS, UNKNOWN, (int) V4SF_FTYPE_PCV4SF_V4SI }, + { OPTION_MASK_ISA_AVX, CODE_FOR_avx_maskloadpd256, "__builtin_ia32_maskloadpd256", IX86_BUILTIN_MASKLOADPD256, UNKNOWN, (int) V4DF_FTYPE_PCV4DF_V4DI }, + { OPTION_MASK_ISA_AVX, CODE_FOR_avx_maskloadps256, "__builtin_ia32_maskloadps256", IX86_BUILTIN_MASKLOADPS256, UNKNOWN, (int) V8SF_FTYPE_PCV8SF_V8SI }, + { OPTION_MASK_ISA_AVX, CODE_FOR_avx_maskstorepd, "__builtin_ia32_maskstorepd", IX86_BUILTIN_MASKSTOREPD, UNKNOWN, (int) VOID_FTYPE_PV2DF_V2DI_V2DF }, + { OPTION_MASK_ISA_AVX, CODE_FOR_avx_maskstoreps, "__builtin_ia32_maskstoreps", IX86_BUILTIN_MASKSTOREPS, UNKNOWN, (int) VOID_FTYPE_PV4SF_V4SI_V4SF }, + { OPTION_MASK_ISA_AVX, CODE_FOR_avx_maskstorepd256, "__builtin_ia32_maskstorepd256", IX86_BUILTIN_MASKSTOREPD256, UNKNOWN, (int) VOID_FTYPE_PV4DF_V4DI_V4DF }, + { OPTION_MASK_ISA_AVX, CODE_FOR_avx_maskstoreps256, "__builtin_ia32_maskstoreps256", IX86_BUILTIN_MASKSTOREPS256, UNKNOWN, (int) VOID_FTYPE_PV8SF_V8SI_V8SF }, { OPTION_MASK_ISA_LWP, CODE_FOR_lwp_llwpcb, "__builtin_ia32_llwpcb", IX86_BUILTIN_LLWPCB, UNKNOWN, (int) VOID_FTYPE_PVOID }, { OPTION_MASK_ISA_LWP, CODE_FOR_lwp_slwpcb, "__builtin_ia32_slwpcb", IX86_BUILTIN_SLWPCB, UNKNOWN, (int) PVOID_FTYPE_VOID }, @@ -26821,18 +26821,18 @@ ix86_expand_special_args_builtin (const struct builtin_description *d, klass = load; memory = 1; break; - case V8SF_FTYPE_PCV8SF_V8SF: - case V4DF_FTYPE_PCV4DF_V4DF: - case V4SF_FTYPE_PCV4SF_V4SF: - case V2DF_FTYPE_PCV2DF_V2DF: + case V8SF_FTYPE_PCV8SF_V8SI: + case V4DF_FTYPE_PCV4DF_V4DI: + case V4SF_FTYPE_PCV4SF_V4SI: + case V2DF_FTYPE_PCV2DF_V2DI: nargs = 2; klass = load; memory = 0; break; - case VOID_FTYPE_PV8SF_V8SF_V8SF: - case VOID_FTYPE_PV4DF_V4DF_V4DF: - case VOID_FTYPE_PV4SF_V4SF_V4SF: - case VOID_FTYPE_PV2DF_V2DF_V2DF: + case VOID_FTYPE_PV8SF_V8SI_V8SF: + case VOID_FTYPE_PV4DF_V4DI_V4DF: + case VOID_FTYPE_PV4SF_V4SI_V4SF: + case VOID_FTYPE_PV2DF_V2DI_V2DF: nargs = 2; klass = store; /* Reserve memory operand for target. */ diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index a942a2b1717..c6636a6d01e 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -11938,7 +11938,7 @@ [(set (match_operand:AVXMODEF2P 0 "register_operand" "=x") (unspec:AVXMODEF2P [(match_operand:AVXMODEF2P 1 "memory_operand" "m") - (match_operand:AVXMODEF2P 2 "register_operand" "x") + (match_operand:<avxpermvecmode> 2 "register_operand" "x") (match_dup 0)] UNSPEC_MASKLOAD))] "TARGET_AVX" @@ -11951,7 +11951,7 @@ (define_insn "avx_maskstore<ssemodesuffix><avxmodesuffix>" [(set (match_operand:AVXMODEF2P 0 "memory_operand" "=m") (unspec:AVXMODEF2P - [(match_operand:AVXMODEF2P 1 "register_operand" "x") + [(match_operand:<avxpermvecmode> 1 "register_operand" "x") (match_operand:AVXMODEF2P 2 "register_operand" "x") (match_dup 0)] UNSPEC_MASKSTORE))] diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index 5018e4114f6..1842555502b 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -2007,7 +2007,10 @@ ia64_expand_unpack (rtx operands[3], bool unsignedp, bool highp) gcc_assert (!neg); } - emit_insn (gen (gen_lowpart (mode, operands[0]), operands[1], x)); + if (TARGET_BIG_ENDIAN) + emit_insn (gen (gen_lowpart (mode, operands[0]), x, operands[1])); + else + emit_insn (gen (gen_lowpart (mode, operands[0]), operands[1], x)); } /* Emit an integral vector widening sum operations. */ @@ -2058,8 +2061,16 @@ ia64_expand_widen_sum (rtx operands[3], bool unsignedp) h = gen_reg_rtx (wmode); s = gen_reg_rtx (wmode); - emit_insn (unpack_l (gen_lowpart (mode, l), operands[1], x)); - emit_insn (unpack_h (gen_lowpart (mode, h), operands[1], x)); + if (TARGET_BIG_ENDIAN) + { + emit_insn (unpack_l (gen_lowpart (mode, l), x, operands[1])); + emit_insn (unpack_h (gen_lowpart (mode, h), x, operands[1])); + } + else + { + emit_insn (unpack_l (gen_lowpart (mode, l), operands[1], x)); + emit_insn (unpack_h (gen_lowpart (mode, h), operands[1], x)); + } emit_insn (plus (s, l, operands[2])); emit_insn (plus (operands[0], h, s)); } @@ -2082,7 +2093,10 @@ ia64_expand_widen_mul_v4hi (rtx operands[3], bool unsignedp, bool highp) emit_insn (mulhigh (h, operands[1], operands[2], GEN_INT (16))); interl = highp ? gen_vec_interleave_highv4hi : gen_vec_interleave_lowv4hi; - emit_insn (interl (gen_lowpart (V4HImode, operands[0]), l, h)); + if (TARGET_BIG_ENDIAN) + emit_insn (interl (gen_lowpart (V4HImode, operands[0]), h, l)); + else + emit_insn (interl (gen_lowpart (V4HImode, operands[0]), l, h)); } /* Emit a signed or unsigned V8QI dot product operation. */ @@ -2115,14 +2129,28 @@ ia64_expand_dot_prod_v8qi (rtx operands[4], bool unsignedp) h1 = gen_reg_rtx (V4HImode); h2 = gen_reg_rtx (V4HImode); - emit_insn (gen_vec_interleave_lowv8qi - (gen_lowpart (V8QImode, l1), operands[1], x1)); - emit_insn (gen_vec_interleave_lowv8qi - (gen_lowpart (V8QImode, l2), operands[2], x2)); - emit_insn (gen_vec_interleave_highv8qi - (gen_lowpart (V8QImode, h1), operands[1], x1)); - emit_insn (gen_vec_interleave_highv8qi - (gen_lowpart (V8QImode, h2), operands[2], x2)); + if (TARGET_BIG_ENDIAN) + { + emit_insn (gen_vec_interleave_lowv8qi + (gen_lowpart (V8QImode, l1), x1, operands[1])); + emit_insn (gen_vec_interleave_lowv8qi + (gen_lowpart (V8QImode, l2), x2, operands[2])); + emit_insn (gen_vec_interleave_highv8qi + (gen_lowpart (V8QImode, h1), x1, operands[1])); + emit_insn (gen_vec_interleave_highv8qi + (gen_lowpart (V8QImode, h2), x2, operands[2])); + } + else + { + emit_insn (gen_vec_interleave_lowv8qi + (gen_lowpart (V8QImode, l1), operands[1], x1)); + emit_insn (gen_vec_interleave_lowv8qi + (gen_lowpart (V8QImode, l2), operands[2], x2)); + emit_insn (gen_vec_interleave_highv8qi + (gen_lowpart (V8QImode, h1), operands[1], x1)); + emit_insn (gen_vec_interleave_highv8qi + (gen_lowpart (V8QImode, h2), operands[2], x2)); + } p1 = gen_reg_rtx (V2SImode); p2 = gen_reg_rtx (V2SImode); diff --git a/gcc/config/ia64/vect.md b/gcc/config/ia64/vect.md index c9dbddc63ea..36db5753e1c 100644 --- a/gcc/config/ia64/vect.md +++ b/gcc/config/ia64/vect.md @@ -370,7 +370,7 @@ [(set (match_operand:V2SI 0 "gr_register_operand" "") (mult:V2SI (match_operand:V2SI 1 "gr_register_operand" "r") (match_operand:V2SI 2 "gr_register_operand" "r")))] - "" + "!TARGET_BIG_ENDIAN" { rtx t0, t1, t2, t3, t4, t5, t6, t7, x; rtx op1h = gen_lowpart (V4HImode, operands[1]); @@ -709,7 +709,13 @@ (const_int 2) (const_int 10) (const_int 3) (const_int 11)])))] "" - "unpack1.l %0 = %r2, %r1" +{ + /* Recall that vector elements are numbered in memory order. */ + if (TARGET_BIG_ENDIAN) + return "%,unpack1.l %0 = %r1, %r2"; + else + return "%,unpack1.l %0 = %r2, %r1"; +} [(set_attr "itanium_class" "mmshf")]) (define_insn "vec_interleave_highv8qi" @@ -723,7 +729,13 @@ (const_int 6) (const_int 14) (const_int 7) (const_int 15)])))] "" - "unpack1.h %0 = %r2, %r1" +{ + /* Recall that vector elements are numbered in memory order. */ + if (TARGET_BIG_ENDIAN) + return "%,unpack1.h %0 = %r1, %r2"; + else + return "%,unpack1.h %0 = %r2, %r1"; +} [(set_attr "itanium_class" "mmshf")]) (define_insn "mix1_r" @@ -857,7 +869,10 @@ "" { rtx temp = gen_reg_rtx (V8QImode); - emit_insn (gen_mix1_r (temp, operands[1], operands[2])); + if (TARGET_BIG_ENDIAN) + emit_insn (gen_mix1_l (temp, operands[2], operands[1])); + else + emit_insn (gen_mix1_r (temp, operands[1], operands[2])); emit_insn (gen_mux1_alt (operands[0], temp)); DONE; }) @@ -869,7 +884,10 @@ "" { rtx temp = gen_reg_rtx (V8QImode); - emit_insn (gen_mix1_l (temp, operands[1], operands[2])); + if (TARGET_BIG_ENDIAN) + emit_insn (gen_mix1_r (temp, operands[2], operands[1])); + else + emit_insn (gen_mix1_l (temp, operands[1], operands[2])); emit_insn (gen_mux1_alt (operands[0], temp)); DONE; }) @@ -885,7 +903,13 @@ (const_int 1) (const_int 5)])))] "" - "unpack2.l %0 = %r2, %r1" +{ + /* Recall that vector elements are numbered in memory order. */ + if (TARGET_BIG_ENDIAN) + return "%,unpack2.l %0 = %r1, %r2"; + else + return "%,unpack2.l %0 = %r2, %r1"; +} [(set_attr "itanium_class" "mmshf")]) (define_insn "vec_interleave_highv4hi" @@ -899,7 +923,13 @@ (const_int 3) (const_int 7)])))] "" - "unpack2.h %0 = %r2, %r1" +{ + /* Recall that vector elements are numbered in memory order. */ + if (TARGET_BIG_ENDIAN) + return "%,unpack2.h %0 = %r1, %r2"; + else + return "%,unpack2.h %0 = %r2, %r1"; +} [(set_attr "itanium_class" "mmshf")]) (define_insn "mix2_r" @@ -958,13 +988,13 @@ (const_int 2) (const_int 1) (const_int 3)])))] - "") + "!TARGET_BIG_ENDIAN") (define_expand "vec_extract_evenv4hi" [(match_operand:V4HI 0 "gr_register_operand") (match_operand:V4HI 1 "gr_reg_or_0_operand") (match_operand:V4HI 2 "gr_reg_or_0_operand")] - "" + "!TARGET_BIG_ENDIAN" { rtx temp = gen_reg_rtx (V4HImode); emit_insn (gen_mix2_r (temp, operands[1], operands[2])); @@ -976,7 +1006,7 @@ [(match_operand:V4HI 0 "gr_register_operand") (match_operand:V4HI 1 "gr_reg_or_0_operand") (match_operand:V4HI 2 "gr_reg_or_0_operand")] - "" + "!TARGET_BIG_ENDIAN" { rtx temp = gen_reg_rtx (V4HImode); emit_insn (gen_mix2_l (temp, operands[1], operands[2])); @@ -1002,7 +1032,13 @@ (parallel [(const_int 0) (const_int 2)])))] "" - "unpack4.l %0 = %r2, %r1" +{ + /* Recall that vector elements are numbered in memory order. */ + if (TARGET_BIG_ENDIAN) + return "%,unpack4.h %0 = %r1, %r2"; + else + return "%,unpack4.l %0 = %r2, %r1"; +} [(set_attr "itanium_class" "mmshf")]) ;; Note that mix4.l performs the exact same operation. @@ -1015,14 +1051,20 @@ (parallel [(const_int 1) (const_int 3)])))] "" - "unpack4.h %0 = %r2, %r1" +{ + /* Recall that vector elements are numbered in memory order. */ + if (TARGET_BIG_ENDIAN) + return "%,unpack4.l %0 = %r1, %r2"; + else + return "%,unpack4.h %0 = %r2, %r1"; +} [(set_attr "itanium_class" "mmshf")]) (define_expand "vec_extract_evenv2si" [(match_operand:V2SI 0 "gr_register_operand" "") (match_operand:V2SI 1 "gr_register_operand" "") (match_operand:V2SI 2 "gr_register_operand" "")] - "" + "!TARGET_BIG_ENDIAN" { emit_insn (gen_vec_interleave_lowv2si (operands[0], operands[1], operands[2])); @@ -1033,7 +1075,7 @@ [(match_operand:V2SI 0 "gr_register_operand" "") (match_operand:V2SI 1 "gr_register_operand" "") (match_operand:V2SI 2 "gr_register_operand" "")] - "" + "!TARGET_BIG_ENDIAN" { emit_insn (gen_vec_interleave_highv2si (operands[0], operands[1], operands[2])); @@ -1397,7 +1439,7 @@ [(match_operand:V2SF 0 "gr_register_operand" "") (match_operand:V2SF 1 "gr_register_operand" "") (match_operand:V2SF 2 "gr_register_operand" "")] - "" + "!TARGET_BIG_ENDIAN" { emit_insn (gen_vec_interleave_lowv2sf (operands[0], operands[1], operands[2])); @@ -1408,7 +1450,7 @@ [(match_operand:V2SF 0 "gr_register_operand" "") (match_operand:V2SF 1 "gr_register_operand" "") (match_operand:V2SF 2 "gr_register_operand" "")] - "" + "!TARGET_BIG_ENDIAN" { emit_insn (gen_vec_interleave_highv2sf (operands[0], operands[1], operands[2])); @@ -1540,7 +1582,7 @@ [(match_operand:V8QI 0 "gr_register_operand" "") (match_operand:V4HI 1 "gr_register_operand" "") (match_operand:V4HI 2 "gr_register_operand" "")] - "" + "!TARGET_BIG_ENDIAN" { rtx op1 = gen_lowpart(V8QImode, operands[1]); rtx op2 = gen_lowpart(V8QImode, operands[2]); @@ -1552,7 +1594,7 @@ [(match_operand:V4HI 0 "gr_register_operand" "") (match_operand:V2SI 1 "gr_register_operand" "") (match_operand:V2SI 2 "gr_register_operand" "")] - "" + "!TARGET_BIG_ENDIAN" { rtx op1 = gen_lowpart(V4HImode, operands[1]); rtx op2 = gen_lowpart(V4HImode, operands[2]); diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 35705469192..a534638541d 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -1669,10 +1669,13 @@ mips_classify_symbol (const_rtx x, enum mips_symbol_context context) if (GET_CODE (x) == LABEL_REF) { - /* LABEL_REFs are used for jump tables as well as text labels. - Only return SYMBOL_PC_RELATIVE if we know the label is in - the text section. */ - if (TARGET_MIPS16_SHORT_JUMP_TABLES) + /* Only return SYMBOL_PC_RELATIVE if we are generating MIPS16 + code and if we know that the label is in the current function's + text section. LABEL_REFs are used for jump tables as well as + text labels, so we must check whether jump tables live in the + text section. */ + if (TARGET_MIPS16_SHORT_JUMP_TABLES + && !LABEL_REF_NONLOCAL_P (x)) return SYMBOL_PC_RELATIVE; if (TARGET_ABICALLS && !TARGET_ABSOLUTE_ABICALLS) diff --git a/gcc/config/pa/pa-hpux.h b/gcc/config/pa/pa-hpux.h index 69a9d1905f7..f167e133eb5 100644 --- a/gcc/config/pa/pa-hpux.h +++ b/gcc/config/pa/pa-hpux.h @@ -22,6 +22,9 @@ along with GCC; see the file COPYING3. If not see #undef TARGET_HPUX #define TARGET_HPUX 1 +#undef HPUX_LONG_DOUBLE_LIBRARY +#define HPUX_LONG_DOUBLE_LIBRARY 1 + #undef TARGET_DEFAULT #define TARGET_DEFAULT MASK_BIG_SWITCH @@ -33,7 +36,6 @@ along with GCC; see the file COPYING3. If not see #define PTRDIFF_TYPE "int" #define LONG_DOUBLE_TYPE_SIZE 128 -#define HPUX_LONG_DOUBLE_LIBRARY #define FLOAT_LIB_COMPARE_RETURNS_BOOL(MODE, COMPARISON) ((MODE) == TFmode) /* GCC always defines __STDC__. HP C++ compilers don't define it. This diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c index 89f7e500820..98267b0ca63 100644 --- a/gcc/config/pa/pa.c +++ b/gcc/config/pa/pa.c @@ -46,6 +46,7 @@ along with GCC; see the file COPYING3. If not see #include "tm_p.h" #include "target.h" #include "target-def.h" +#include "langhooks.h" #include "df.h" /* Return nonzero if there is a bypass for the output of @@ -129,6 +130,7 @@ static void pa_asm_out_constructor (rtx, int); static void pa_asm_out_destructor (rtx, int); #endif static void pa_init_builtins (void); +static rtx pa_expand_builtin (tree, rtx, rtx, enum machine_mode mode, int); static rtx hppa_builtin_saveregs (void); static void hppa_va_start (tree, rtx); static tree hppa_gimplify_va_arg_expr (tree, tree, gimple_seq *, gimple_seq *); @@ -151,7 +153,7 @@ static void output_deferred_profile_counters (void) ATTRIBUTE_UNUSED; #ifdef ASM_OUTPUT_EXTERNAL_REAL static void pa_hpux_file_end (void); #endif -#ifdef HPUX_LONG_DOUBLE_LIBRARY +#if HPUX_LONG_DOUBLE_LIBRARY static void pa_hpux_init_libfuncs (void); #endif static rtx pa_struct_value_rtx (tree, int); @@ -181,6 +183,7 @@ static bool pa_print_operand_punct_valid_p (unsigned char); static rtx pa_internal_arg_pointer (void); static bool pa_can_eliminate (const int, const int); static void pa_conditional_register_usage (void); +static enum machine_mode pa_c_mode_for_suffix (char); static section *pa_function_section (tree, enum node_frequency, bool, bool); /* The following extra sections are only used for SOM. */ @@ -317,6 +320,9 @@ static const struct default_options pa_option_optimization_table[] = #undef TARGET_INIT_BUILTINS #define TARGET_INIT_BUILTINS pa_init_builtins +#undef TARGET_EXPAND_BUILTIN +#define TARGET_EXPAND_BUILTIN pa_expand_builtin + #undef TARGET_REGISTER_MOVE_COST #define TARGET_REGISTER_MOVE_COST hppa_register_move_cost #undef TARGET_RTX_COSTS @@ -327,7 +333,7 @@ static const struct default_options pa_option_optimization_table[] = #undef TARGET_MACHINE_DEPENDENT_REORG #define TARGET_MACHINE_DEPENDENT_REORG pa_reorg -#ifdef HPUX_LONG_DOUBLE_LIBRARY +#if HPUX_LONG_DOUBLE_LIBRARY #undef TARGET_INIT_LIBFUNCS #define TARGET_INIT_LIBFUNCS pa_hpux_init_libfuncs #endif @@ -389,6 +395,8 @@ static const struct default_options pa_option_optimization_table[] = #define TARGET_CAN_ELIMINATE pa_can_eliminate #undef TARGET_CONDITIONAL_REGISTER_USAGE #define TARGET_CONDITIONAL_REGISTER_USAGE pa_conditional_register_usage +#undef TARGET_C_MODE_FOR_SUFFIX +#define TARGET_C_MODE_FOR_SUFFIX pa_c_mode_for_suffix #undef TARGET_ASM_FUNCTION_SECTION #define TARGET_ASM_FUNCTION_SECTION pa_function_section @@ -598,6 +606,17 @@ pa_option_override (void) init_machine_status = pa_init_machine_status; } +enum pa_builtins +{ + PA_BUILTIN_COPYSIGNQ, + PA_BUILTIN_FABSQ, + PA_BUILTIN_INFQ, + PA_BUILTIN_HUGE_VALQ, + PA_BUILTIN_max +}; + +static GTY(()) tree pa_builtins[(int) PA_BUILTIN_max]; + static void pa_init_builtins (void) { @@ -613,6 +632,86 @@ pa_init_builtins (void) if (built_in_decls [BUILT_IN_FINITEF]) set_user_assembler_name (built_in_decls [BUILT_IN_FINITEF], "_Isfinitef"); #endif + + if (HPUX_LONG_DOUBLE_LIBRARY) + { + tree decl, ftype; + + /* Under HPUX, the __float128 type is a synonym for "long double". */ + (*lang_hooks.types.register_builtin_type) (long_double_type_node, + "__float128"); + + /* TFmode support builtins. */ + ftype = build_function_type_list (long_double_type_node, + long_double_type_node, + NULL_TREE); + decl = add_builtin_function ("__builtin_fabsq", ftype, + PA_BUILTIN_FABSQ, BUILT_IN_MD, + "_U_Qfabs", NULL_TREE); + TREE_READONLY (decl) = 1; + pa_builtins[PA_BUILTIN_FABSQ] = decl; + + ftype = build_function_type_list (long_double_type_node, + long_double_type_node, + long_double_type_node, + NULL_TREE); + decl = add_builtin_function ("__builtin_copysignq", ftype, + PA_BUILTIN_COPYSIGNQ, BUILT_IN_MD, + "_U_Qfcopysign", NULL_TREE); + TREE_READONLY (decl) = 1; + pa_builtins[PA_BUILTIN_COPYSIGNQ] = decl; + + ftype = build_function_type (long_double_type_node, void_list_node); + decl = add_builtin_function ("__builtin_infq", ftype, + PA_BUILTIN_INFQ, BUILT_IN_MD, + NULL, NULL_TREE); + pa_builtins[PA_BUILTIN_INFQ] = decl; + + decl = add_builtin_function ("__builtin_huge_valq", ftype, + PA_BUILTIN_HUGE_VALQ, BUILT_IN_MD, + NULL, NULL_TREE); + pa_builtins[PA_BUILTIN_HUGE_VALQ] = decl; + } +} + +static rtx +pa_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, + enum machine_mode mode ATTRIBUTE_UNUSED, + int ignore ATTRIBUTE_UNUSED) +{ + tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); + unsigned int fcode = DECL_FUNCTION_CODE (fndecl); + + switch (fcode) + { + case PA_BUILTIN_FABSQ: + case PA_BUILTIN_COPYSIGNQ: + return expand_call (exp, target, ignore); + + case PA_BUILTIN_INFQ: + case PA_BUILTIN_HUGE_VALQ: + { + enum machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp)); + REAL_VALUE_TYPE inf; + rtx tmp; + + real_inf (&inf); + tmp = CONST_DOUBLE_FROM_REAL_VALUE (inf, target_mode); + + tmp = validize_mem (force_const_mem (target_mode, tmp)); + + if (target == 0) + target = gen_reg_rtx (target_mode); + + emit_move_insn (target, tmp); + return target; + } + + default: + gcc_unreachable (); + } + + return NULL_RTX; } /* Function to init struct machine_function. @@ -5522,7 +5621,7 @@ output_deferred_plabels (void) } } -#ifdef HPUX_LONG_DOUBLE_LIBRARY +#if HPUX_LONG_DOUBLE_LIBRARY /* Initialize optabs to point to HPUX long double emulation routines. */ static void pa_hpux_init_libfuncs (void) @@ -10243,6 +10342,20 @@ pa_conditional_register_usage (void) fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1; } +/* Target hook for c_mode_for_suffix. */ + +static enum machine_mode +pa_c_mode_for_suffix (char suffix) +{ + if (HPUX_LONG_DOUBLE_LIBRARY) + { + if (suffix == 'q') + return TFmode; + } + + return VOIDmode; +} + /* Target hook for function_section. */ static section * diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h index 0a0250ff3b9..41af1f12f6e 100644 --- a/gcc/config/pa/pa.h +++ b/gcc/config/pa/pa.h @@ -86,6 +86,11 @@ extern int flag_pa_unix; #define TARGET_HPUX_11_11 0 #endif +/* HP-UX long double library. */ +#ifndef HPUX_LONG_DOUBLE_LIBRARY +#define HPUX_LONG_DOUBLE_LIBRARY 0 +#endif + /* The following three defines are potential target switches. The current defines are optimal given the current capabilities of GAS and GNU ld. */ diff --git a/gcc/config/pa/quadlib.c b/gcc/config/pa/quadlib.c index 06c2292b869..2c1160015ed 100644 --- a/gcc/config/pa/quadlib.c +++ b/gcc/config/pa/quadlib.c @@ -58,6 +58,7 @@ int _U_Qford (long double, long double); int _U_Qfcomp (long double, long double); long double _U_Qfneg (long double); +long double _U_Qfcopysign (long double, long double); #ifdef __LP64__ int __U_Qfcnvfxt_quad_to_sgl (long double); @@ -160,7 +161,6 @@ _U_Qfcomp (long double a, long double b) return (_U_Qfcmp (a, b, QCMP_UNORD | QCMP_EQ | QCMP_GT) != 0 ? 1 : -1); } - /* Negate long double A. */ long double _U_Qfneg (long double a) @@ -176,6 +176,23 @@ _U_Qfneg (long double a) return u.ld; } +/* Return long double A with sign changed to sign of long double B. */ +long double +_U_Qfcopysign (long double a, long double b) +{ + union + { + long double ld; + int i[4]; + } ua, ub; + + ua.ld = a; + ub.ld = b; + ua.i[0] &= 0x7fffffff; + ua.i[0] |= (0x80000000 & ub.i[0]); + return ua.ld; +} + #ifdef __LP64__ /* This routine is only necessary for the PA64 port; for reasons unknown _U_Qfcnvfxt_quad_to_sgl returns the integer in the high 32bits of the diff --git a/gcc/config/rx/predicates.md b/gcc/config/rx/predicates.md index e1b3f0c9f91..608fca5f925 100644 --- a/gcc/config/rx/predicates.md +++ b/gcc/config/rx/predicates.md @@ -37,19 +37,19 @@ ;; Only small integers or a value in a register are permitted. (define_predicate "rx_shift_operand" - (match_code "const_int,reg") - { - if (CONST_INT_P (op)) - return IN_RANGE (INTVAL (op), 0, 31); - return true; - } + (ior (match_operand 0 "register_operand") + (and (match_code "const_int") + (match_test "IN_RANGE (INTVAL (op), 0, 31)"))) ) (define_predicate "rx_constshift_operand" - (match_code "const_int") - { - return IN_RANGE (INTVAL (op), 0, 31); - } + (and (match_code "const_int") + (match_test "IN_RANGE (INTVAL (op), 0, 31)")) +) + +(define_predicate "rx_restricted_mem_operand" + (and (match_code "mem") + (match_test "rx_is_restricted_memory_address (XEXP (op, 0), mode)")) ) ;; Check that the operand is suitable as the source operand @@ -57,20 +57,9 @@ ;; and a restricted subset of memory addresses are allowed. (define_predicate "rx_source_operand" - (match_code "const_int,const_double,const,symbol_ref,label_ref,reg,mem") - { - if (CONSTANT_P (op)) - return rx_is_legitimate_constant (op); - - if (! MEM_P (op)) - return true; - - /* Do not allow size conversions whilst accessing memory. */ - if (GET_MODE (op) != mode) - return false; - - return rx_is_restricted_memory_address (XEXP (op, 0), mode); - } + (ior (match_operand 0 "register_operand") + (match_operand 0 "immediate_operand") + (match_operand 0 "rx_restricted_mem_operand")) ) ;; Check that the operand is suitable as the source operand @@ -79,16 +68,8 @@ ;; CONST_INTs are not. (define_predicate "rx_compare_operand" - (match_code "subreg,reg,mem") - { - if (GET_CODE (op) == SUBREG) - return REG_P (XEXP (op, 0)); - - if (! MEM_P (op)) - return true; - - return rx_is_restricted_memory_address (XEXP (op, 0), mode); - } + (ior (match_operand 0 "register_operand") + (match_operand 0 "rx_restricted_mem_operand")) ) ;; Return true if OP is a store multiple operation. This looks like: @@ -293,3 +274,24 @@ element = XVECEXP (op, 0, count - 1); return GET_CODE (element) == RETURN; }) + +(define_predicate "label_ref_operand" + (match_code "label_ref") +) + +(define_predicate "rx_z_comparison_operator" + (match_code "eq,ne") +) + +(define_predicate "rx_zs_comparison_operator" + (match_code "eq,ne,lt,ge") +) + +;; GT, LE, UNLE, UNGT omitted due to operand swap required. +(define_predicate "rx_fp_comparison_operator" + (match_code "eq,ne,lt,ge,ordered,unordered,uneq,unlt,unge,ltgt") +) + +(define_predicate "rshift_operator" + (match_code "ashiftrt,lshiftrt") +) diff --git a/gcc/config/rx/rx-modes.def b/gcc/config/rx/rx-modes.def index 0c4c192a265..31e3225c677 100644 --- a/gcc/config/rx/rx-modes.def +++ b/gcc/config/rx/rx-modes.def @@ -21,3 +21,5 @@ CC_MODE (CC_ZS); CC_MODE (CC_ZSO); CC_MODE (CC_ZSC); + +CC_MODE (CC_F); /* fcmp */ diff --git a/gcc/config/rx/rx-protos.h b/gcc/config/rx/rx-protos.h index 528ccb33e1b..3c3f2d47124 100644 --- a/gcc/config/rx/rx-protos.h +++ b/gcc/config/rx/rx-protos.h @@ -24,22 +24,24 @@ /* A few abbreviations to make the prototypes shorter. */ #define Mmode enum machine_mode #define Fargs CUMULATIVE_ARGS +#define Rcode enum rtx_code extern void rx_expand_prologue (void); extern int rx_initial_elimination_offset (int, int); #ifdef RTX_CODE -extern bool rx_compare_redundant (rtx); extern void rx_emit_stack_popm (rtx *, bool); extern void rx_emit_stack_pushm (rtx *); extern void rx_expand_epilogue (bool); -extern bool rx_expand_insv (rtx *); -extern const char * rx_gen_cond_branch_template (rtx, bool); extern char * rx_gen_move_template (rtx *, bool); extern bool rx_is_legitimate_constant (rtx); extern bool rx_is_mode_dependent_addr (rtx); extern bool rx_is_restricted_memory_address (rtx, Mmode); extern void rx_notice_update_cc (rtx body, rtx insn); +extern void rx_split_cbranch (Mmode, Rcode, rtx, rtx, rtx); +extern bool rx_split_fp_compare (Rcode, Rcode *, Rcode *); +extern Mmode rx_select_cc_mode (Rcode, rtx, rtx); +extern bool rx_match_ccmode (rtx, Mmode); #endif #endif /* GCC_RX_PROTOS_H */ diff --git a/gcc/config/rx/rx.c b/gcc/config/rx/rx.c index 8f6f384c4c2..0179b1ff520 100644 --- a/gcc/config/rx/rx.c +++ b/gcc/config/rx/rx.c @@ -53,6 +53,15 @@ static void rx_print_operand (FILE *, rtx, int); +#define CC_FLAG_S (1 << 0) +#define CC_FLAG_Z (1 << 1) +#define CC_FLAG_O (1 << 2) +#define CC_FLAG_C (1 << 3) +#define CC_FLAG_FP (1 << 4) /* fake, to differentiate CC_Fmode */ + +static unsigned int flags_from_mode (enum machine_mode mode); +static unsigned int flags_from_code (enum rtx_code code); + enum rx_cpu_types rx_cpu_type = RX600; /* Return true if OP is a reference to an object in a small data area. */ @@ -354,8 +363,6 @@ rx_assemble_integer (rtx x, unsigned int size, int is_aligned) } -int rx_float_compare_mode; - /* Handles the insertion of a single operand into the assembler output. The %<letter> directives supported are: @@ -395,21 +402,82 @@ rx_print_operand (FILE * file, rtx op, int letter) break; case 'B': - switch (GET_CODE (op)) - { - case LT: fprintf (file, "lt"); break; - case GE: fprintf (file, "ge"); break; - case GT: fprintf (file, "gt"); break; - case LE: fprintf (file, "le"); break; - case GEU: fprintf (file, "geu"); break; - case LTU: fprintf (file, "ltu"); break; - case GTU: fprintf (file, "gtu"); break; - case LEU: fprintf (file, "leu"); break; - case EQ: fprintf (file, "eq"); break; - case NE: fprintf (file, "ne"); break; - default: debug_rtx (op); gcc_unreachable (); - } - break; + { + enum rtx_code code = GET_CODE (op); + enum machine_mode mode = GET_MODE (XEXP (op, 0)); + const char *ret; + + if (mode == CC_Fmode) + { + /* C flag is undefined, and O flag carries unordered. None of the + branch combinations that include O use it helpfully. */ + switch (code) + { + case ORDERED: + ret = "no"; + break; + case UNORDERED: + ret = "o"; + break; + case LT: + ret = "n"; + break; + case GE: + ret = "pz"; + break; + case EQ: + ret = "eq"; + break; + case NE: + ret = "ne"; + break; + default: + gcc_unreachable (); + } + } + else + { + switch (code) + { + case LT: + ret = "n"; + break; + case GE: + ret = "pz"; + break; + case GT: + ret = "gt"; + break; + case LE: + ret = "le"; + break; + case GEU: + ret = "geu"; + break; + case LTU: + ret = "ltu"; + break; + case GTU: + ret = "gtu"; + break; + case LEU: + ret = "leu"; + break; + case EQ: + ret = "eq"; + break; + case NE: + ret = "ne"; + break; + default: + gcc_unreachable (); + } + gcc_checking_assert ((flags_from_code (code) + & ~flags_from_mode (mode)) == 0); + } + fputs (ret, file); + break; + } case 'C': gcc_assert (CONST_INT_P (op)); @@ -700,51 +768,6 @@ rx_gen_move_template (rtx * operands, bool is_movu) extension, src_template, dst_template); return out_template; } - -/* Returns an assembler template for a conditional branch instruction. */ - -const char * -rx_gen_cond_branch_template (rtx condition, bool reversed) -{ - enum rtx_code code = GET_CODE (condition); - - if (reversed) - { - if (rx_float_compare_mode) - code = reverse_condition_maybe_unordered (code); - else - code = reverse_condition (code); - } - - /* We do not worry about encoding the branch length here as GAS knows - how to choose the smallest version, and how to expand a branch that - is to a destination that is out of range. */ - - switch (code) - { - case UNEQ: return "bo\t1f\n\tbeq\t%0\n1:"; - case LTGT: return "bo\t1f\n\tbne\t%0\n1:"; - case UNLT: return "bo\t1f\n\tbn\t%0\n1:"; - case UNGE: return "bo\t1f\n\tbpz\t%0\n1:"; - case UNLE: return "bo\t1f\n\tbgt\t1f\n\tbra\t%0\n1:"; - case UNGT: return "bo\t1f\n\tble\t1f\n\tbra\t%0\n1:"; - case UNORDERED: return "bo\t%0"; - case ORDERED: return "bno\t%0"; - - case LT: return rx_float_compare_mode ? "bn\t%0" : "blt\t%0"; - case GE: return rx_float_compare_mode ? "bpz\t%0" : "bge\t%0"; - case GT: return "bgt\t%0"; - case LE: return "ble\t%0"; - case GEU: return "bgeu\t%0"; - case LTU: return "bltu\t%0"; - case GTU: return "bgtu\t%0"; - case LEU: return "bleu\t%0"; - case EQ: return "beq\t%0"; - case NE: return "bne\t%0"; - default: - gcc_unreachable (); - } -} /* Return VALUE rounded up to the next ALIGNMENT boundary. */ @@ -1226,13 +1249,13 @@ gen_rx_store_vector (unsigned int low, unsigned int high) vector = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count)); XVECEXP (vector, 0, 0) = - gen_rtx_SET (SImode, stack_pointer_rtx, + gen_rtx_SET (VOIDmode, stack_pointer_rtx, gen_rtx_MINUS (SImode, stack_pointer_rtx, GEN_INT ((count - 1) * UNITS_PER_WORD))); for (i = 0; i < count - 1; i++) XVECEXP (vector, 0, i + 1) = - gen_rtx_SET (SImode, + gen_rtx_SET (VOIDmode, gen_rtx_MEM (SImode, gen_rtx_MINUS (SImode, stack_pointer_rtx, GEN_INT ((i + 1) * UNITS_PER_WORD))), @@ -1456,12 +1479,12 @@ gen_rx_rtsd_vector (unsigned int adjust, unsigned int low, unsigned int high) vector = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count)); XVECEXP (vector, 0, 0) = - gen_rtx_SET (SImode, stack_pointer_rtx, + gen_rtx_SET (VOIDmode, stack_pointer_rtx, plus_constant (stack_pointer_rtx, adjust)); for (i = 0; i < count - 2; i++) XVECEXP (vector, 0, i + 1) = - gen_rtx_SET (SImode, + gen_rtx_SET (VOIDmode, gen_rtx_REG (SImode, low + i), gen_rtx_MEM (SImode, i == 0 ? stack_pointer_rtx @@ -1485,13 +1508,13 @@ gen_rx_popm_vector (unsigned int low, unsigned int high) vector = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count)); XVECEXP (vector, 0, 0) = - gen_rtx_SET (SImode, stack_pointer_rtx, + gen_rtx_SET (VOIDmode, stack_pointer_rtx, plus_constant (stack_pointer_rtx, (count - 1) * UNITS_PER_WORD)); for (i = 0; i < count - 1; i++) XVECEXP (vector, 0, i + 1) = - gen_rtx_SET (SImode, + gen_rtx_SET (VOIDmode, gen_rtx_REG (SImode, low + i), gen_rtx_MEM (SImode, i == 0 ? stack_pointer_rtx @@ -1824,7 +1847,6 @@ enum rx_builtin RX_BUILTIN_REVW, RX_BUILTIN_RMPA, RX_BUILTIN_ROUND, - RX_BUILTIN_SAT, RX_BUILTIN_SETPSW, RX_BUILTIN_WAIT, RX_BUILTIN_max @@ -1879,7 +1901,6 @@ rx_init_builtins (void) ADD_RX_BUILTIN1 (RACW, "racw", void, integer); ADD_RX_BUILTIN1 (ROUND, "round", intSI, float); ADD_RX_BUILTIN1 (REVW, "revw", intSI, intSI); - ADD_RX_BUILTIN1 (SAT, "sat", intSI, intSI); ADD_RX_BUILTIN1 (WAIT, "wait", void, void); } @@ -2077,8 +2098,6 @@ rx_expand_builtin (tree exp, case RX_BUILTIN_ROUND: return rx_expand_builtin_round (op, target); case RX_BUILTIN_REVW: return rx_expand_int_builtin_1_arg (op, target, gen_revw, false); - case RX_BUILTIN_SAT: return rx_expand_int_builtin_1_arg - (op, target, gen_sat, false); case RX_BUILTIN_WAIT: emit_insn (gen_wait ()); return NULL_RTX; default: @@ -2316,48 +2335,6 @@ rx_is_ms_bitfield_layout (const_tree record_type ATTRIBUTE_UNUSED) /* The packed attribute overrides the MS behaviour. */ return ! TYPE_PACKED (record_type); } - -/* Try to generate code for the "isnv" pattern which inserts bits - into a word. - operands[0] => Location to be altered. - operands[1] => Number of bits to change. - operands[2] => Starting bit. - operands[3] => Value to insert. - Returns TRUE if successful, FALSE otherwise. */ - -bool -rx_expand_insv (rtx * operands) -{ - if (INTVAL (operands[1]) != 1 - || ! CONST_INT_P (operands[3])) - return false; - - if (MEM_P (operands[0]) - && INTVAL (operands[2]) > 7) - return false; - - switch (INTVAL (operands[3])) - { - case 0: - if (MEM_P (operands[0])) - emit_insn (gen_bitclr_in_memory (operands[0], operands[0], - operands[2])); - else - emit_insn (gen_bitclr (operands[0], operands[0], operands[2])); - break; - case 1: - case -1: - if (MEM_P (operands[0])) - emit_insn (gen_bitset_in_memory (operands[0], operands[0], - operands[2])); - else - emit_insn (gen_bitset (operands[0], operands[0], operands[2])); - break; - default: - return false; - } - return true; -} /* Returns true if X a legitimate constant for an immediate operand on the RX. X is already known to satisfy CONSTANT_P. */ @@ -2543,219 +2520,223 @@ rx_trampoline_init (rtx tramp, tree fndecl, rtx chain) } } +static int +rx_memory_move_cost (enum machine_mode mode, reg_class_t regclass, bool in) +{ + return 2 + memory_move_secondary_cost (mode, regclass, in); +} + +/* Convert a CC_MODE to the set of flags that it represents. */ + +static unsigned int +flags_from_mode (enum machine_mode mode) +{ + switch (mode) + { + case CC_ZSmode: + return CC_FLAG_S | CC_FLAG_Z; + case CC_ZSOmode: + return CC_FLAG_S | CC_FLAG_Z | CC_FLAG_O; + case CC_ZSCmode: + return CC_FLAG_S | CC_FLAG_Z | CC_FLAG_C; + case CCmode: + return CC_FLAG_S | CC_FLAG_Z | CC_FLAG_O | CC_FLAG_C; + case CC_Fmode: + return CC_FLAG_FP; + default: + gcc_unreachable (); + } +} + +/* Convert a set of flags to a CC_MODE that can implement it. */ static enum machine_mode -rx_cc_modes_compatible (enum machine_mode m1, enum machine_mode m2) +mode_from_flags (unsigned int f) { - if (m1 == CCmode) - return m2; - if (m2 == CCmode) - return m1; - if (m1 == m2) - return m1; - if (m1 == CC_ZSmode) - return m1; - if (m2 == CC_ZSmode) - return m2; - return VOIDmode; + if (f & CC_FLAG_FP) + return CC_Fmode; + if (f & CC_FLAG_O) + { + if (f & CC_FLAG_C) + return CCmode; + else + return CC_ZSOmode; + } + else if (f & CC_FLAG_C) + return CC_ZSCmode; + else + return CC_ZSmode; } -#define CC_FLAG_S (1 << 0) -#define CC_FLAG_Z (1 << 1) -#define CC_FLAG_O (1 << 2) -#define CC_FLAG_C (1 << 3) +/* Convert an RTX_CODE to the set of flags needed to implement it. + This assumes an integer comparison. */ static unsigned int -flags_needed_for_conditional (rtx conditional) +flags_from_code (enum rtx_code code) { - switch (GET_CODE (conditional)) + switch (code) { + case LT: + case GE: + return CC_FLAG_S; + case GT: case LE: - case GT: return CC_FLAG_S | CC_FLAG_Z | CC_FLAG_O; - + return CC_FLAG_S | CC_FLAG_O | CC_FLAG_Z; + case GEU: + case LTU: + return CC_FLAG_C; + case GTU: case LEU: - case GTU: return CC_FLAG_Z | CC_FLAG_C; + return CC_FLAG_C | CC_FLAG_Z; + case EQ: + case NE: + return CC_FLAG_Z; + default: + gcc_unreachable (); + } +} - case LT: - case GE: return CC_FLAG_S | CC_FLAG_O; +/* Return a CC_MODE of which both M1 and M2 are subsets. */ - case LTU: - case GEU: return CC_FLAG_C; +static enum machine_mode +rx_cc_modes_compatible (enum machine_mode m1, enum machine_mode m2) +{ + unsigned f; - case EQ: - case NE: return CC_FLAG_Z; + /* Early out for identical modes. */ + if (m1 == m2) + return m1; - default: gcc_unreachable (); - } + /* There's no valid combination for FP vs non-FP. */ + f = flags_from_mode (m1) | flags_from_mode (m2); + if (f & CC_FLAG_FP) + return VOIDmode; + + /* Otherwise, see what mode can implement all the flags. */ + return mode_from_flags (f); } -static unsigned int -flags_from_mode (enum machine_mode mode) +/* Return the minimal CC mode needed to implement (CMP_CODE X Y). */ + +enum machine_mode +rx_select_cc_mode (enum rtx_code cmp_code, rtx x, rtx y ATTRIBUTE_UNUSED) { - switch (mode) - { - case CCmode: return CC_FLAG_S | CC_FLAG_Z | CC_FLAG_O | CC_FLAG_C; - case CC_ZSmode: return CC_FLAG_S | CC_FLAG_Z; - case CC_ZSOmode: return CC_FLAG_S | CC_FLAG_Z | CC_FLAG_O; - case CC_ZSCmode: return CC_FLAG_S | CC_FLAG_Z | CC_FLAG_C; - default: gcc_unreachable (); - } + if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT) + return CC_Fmode; + + return mode_from_flags (flags_from_code (cmp_code)); } -/* Returns true if a compare insn is redundant because it - would only set flags that are already set correctly. */ +/* Split the floating-point comparison IN into individual comparisons + O1 and O2. O2 may be UNKNOWN if there is no second comparison. + Return true iff the comparison operands must be swapped. */ bool -rx_compare_redundant (rtx cmp) -{ - unsigned int flags_needed; - unsigned int flags_set; - rtx next; - rtx prev; - rtx source; - rtx dest; - static rtx cc_reg = NULL_RTX; - - if (cc_reg == NULL_RTX) - cc_reg = gen_rtx_REG (CCmode, CC_REGNUM); - - /* We can only eliminate compares against 0. */ - if (GET_CODE (XEXP (SET_SRC (PATTERN (cmp)), 1)) != CONST_INT - || INTVAL (XEXP (SET_SRC (PATTERN (cmp)), 1)) != 0) - return false; +rx_split_fp_compare (enum rtx_code in, enum rtx_code *o1, enum rtx_code *o2) +{ + enum rtx_code cmp1 = in, cmp2 = UNKNOWN; + bool swap = false; - /* Locate the branch insn that follows the - compare and which tests the bits in the PSW. */ - next = cmp; - do + switch (in) { - /* If we have found an insn that sets or clobbers the CC - register and it was not the IF_THEN_ELSE insn that we - are looking for, then the comparison is redundant. */ - if (next != cmp && reg_mentioned_p (cc_reg, PATTERN (next))) - return true; - - next = next_nonnote_insn (next); - - /* If we run out of insns without finding the - user then the comparison is unnecessary. */ - if (next == NULL_RTX) - return true; - - /* If we have found another comparison - insn then the first one is redundant. */ - if (INSN_P (next) - && GET_CODE (PATTERN (next)) == SET - && REG_P (SET_DEST (PATTERN (next))) - && REGNO (SET_DEST (PATTERN (next))) == CC_REGNUM) - return true; + case ORDERED: + case UNORDERED: + case LT: + case GE: + case EQ: + case NE: + break; - /* If we have found another arithmetic/logic insn that - sets the PSW flags then the comparison is redundant. */ - if (INSN_P (next) - && GET_CODE (PATTERN (next)) == PARALLEL - && GET_CODE (XVECEXP (PATTERN (next), 0, 1)) == SET - && REG_P (SET_DEST (XVECEXP (PATTERN (next), 0, 1))) - && REGNO (SET_DEST (XVECEXP (PATTERN (next), 0, 1))) == CC_REGNUM) - return true; + case GT: + case LE: + cmp1 = swap_condition (cmp1); + swap = true; + break; - /* If we have found an unconditional branch then the - PSW flags might be carried along with the jump, so - the comparison is necessary. */ - if (INSN_P (next) && JUMP_P (next)) - { - if (GET_CODE (PATTERN (next)) != SET) - /* If the jump does not involve setting the PC - then it is a return of some kind, and we know - that the comparison is not used. */ - return true; + case UNEQ: + cmp1 = UNORDERED; + cmp2 = EQ; + break; + case UNLT: + cmp1 = UNORDERED; + cmp2 = LT; + break; + case UNGE: + cmp1 = UNORDERED; + cmp2 = GE; + break; + case UNLE: + cmp1 = UNORDERED; + cmp2 = GT; + swap = true; + break; + case UNGT: + cmp1 = UNORDERED; + cmp2 = LE; + swap = true; + break; + case LTGT: + cmp1 = ORDERED; + cmp2 = NE; + break; - if (GET_CODE (SET_SRC (PATTERN (next))) != IF_THEN_ELSE) - return false; - } + default: + gcc_unreachable (); } - while (! INSN_P (next) - || DEBUG_INSN_P (next) - || GET_CODE (PATTERN (next)) != SET - || GET_CODE (SET_SRC (PATTERN (next))) != IF_THEN_ELSE); - - flags_needed = flags_needed_for_conditional (XEXP (SET_SRC (PATTERN (next)), 0)); - - /* Now look to see if there was a previous - instruction which set the PSW bits. */ - source = XEXP (SET_SRC (PATTERN (cmp)), 0); - prev = cmp; - do - { - /* If this insn uses/sets/clobbers the CC register - and it is not the insn that we are looking for - below, then we must need the comparison. */ - if (prev != cmp && reg_mentioned_p (cc_reg, PATTERN (prev))) - return false; - prev = prev_nonnote_insn (prev); + *o1 = cmp1; + *o2 = cmp2; + return swap; +} - if (prev == NULL_RTX) - return false; +/* Split the conditional branch. Emit (COMPARE C1 C2) into CC_REG with + CC_MODE, and use that in branches based on that compare. */ - /* If we encounter an insn which changes the contents of - the register which is the source of the comparison then - we will definitely need the comparison. */ - if (INSN_P (prev) - && GET_CODE (PATTERN (prev)) == SET - && rtx_equal_p (SET_DEST (PATTERN (prev)), source)) - { - /* Unless this instruction is a simple register move - instruction. In which case we can continue our - scan backwards, but now using the *source* of this - set instruction. */ - if (REG_P (SET_SRC (PATTERN (prev)))) - source = SET_SRC (PATTERN (prev)); - /* We can also survive a sign-extension if the test is - for EQ/NE. Note the same does not apply to zero- - extension as this can turn a non-zero bit-pattern - into zero. */ - else if (flags_needed == CC_FLAG_Z - && GET_CODE (SET_SRC (PATTERN (prev))) == SIGN_EXTEND) - source = XEXP (SET_SRC (PATTERN (prev)), 0); - else - return false; - } +void +rx_split_cbranch (enum machine_mode cc_mode, enum rtx_code cmp1, + rtx c1, rtx c2, rtx label) +{ + rtx flags, x; - /* A label means a possible branch into the - code here, so we have to stop scanning. */ - if (LABEL_P (prev)) - return false; - } - while (! INSN_P (prev) - || DEBUG_INSN_P (prev) - || GET_CODE (PATTERN (prev)) != PARALLEL - || GET_CODE (XVECEXP (PATTERN (prev), 0, 1)) != SET - || ! REG_P (SET_DEST (XVECEXP (PATTERN (prev), 0, 1))) - || REGNO (SET_DEST (XVECEXP (PATTERN (prev), 0, 1))) != CC_REGNUM); - - flags_set = flags_from_mode (GET_MODE (SET_DEST (XVECEXP (PATTERN (prev), 0, 1)))); - - dest = SET_DEST (XVECEXP (PATTERN (prev), 0, 0)); - /* The destination of the previous arithmetic/logic instruction - must match the source in the comparison operation. For registers - we ignore the mode as there may have been a sign-extension involved. */ - if (! rtx_equal_p (source, dest)) - { - if (REG_P (source) && REG_P (dest) && REGNO (dest) == REGNO (source)) - ; - else - return false; - } + flags = gen_rtx_REG (cc_mode, CC_REG); + x = gen_rtx_COMPARE (cc_mode, c1, c2); + x = gen_rtx_SET (VOIDmode, flags, x); + emit_insn (x); - return ((flags_set & flags_needed) == flags_needed); + x = gen_rtx_fmt_ee (cmp1, VOIDmode, flags, const0_rtx); + x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, label, pc_rtx); + x = gen_rtx_SET (VOIDmode, pc_rtx, x); + emit_jump_insn (x); } -static int -rx_memory_move_cost (enum machine_mode mode, reg_class_t regclass, bool in) +/* A helper function for matching parallels that set the flags. */ + +bool +rx_match_ccmode (rtx insn, enum machine_mode cc_mode) { - return 2 + memory_move_secondary_cost (mode, regclass, in); + rtx op1, flags; + enum machine_mode flags_mode; + + gcc_checking_assert (XVECLEN (PATTERN (insn), 0) == 2); + + op1 = XVECEXP (PATTERN (insn), 0, 1); + gcc_checking_assert (GET_CODE (SET_SRC (op1)) == COMPARE); + + flags = SET_DEST (op1); + flags_mode = GET_MODE (flags); + + if (GET_MODE (SET_SRC (op1)) != flags_mode) + return false; + if (GET_MODE_CLASS (flags_mode) != MODE_CC) + return false; + + /* Ensure that the mode of FLAGS is compatible with CC_MODE. */ + if (flags_from_mode (flags_mode) & ~flags_from_mode (cc_mode)) + return false; + + return true; } + #undef TARGET_FUNCTION_VALUE #define TARGET_FUNCTION_VALUE rx_function_value diff --git a/gcc/config/rx/rx.h b/gcc/config/rx/rx.h index 35b5d58c4a4..e2c8641685d 100644 --- a/gcc/config/rx/rx.h +++ b/gcc/config/rx/rx.h @@ -595,8 +595,6 @@ typedef unsigned int CUMULATIVE_ARGS; they contain are always computed between two same-section symbols. */ #define JUMP_TABLES_IN_TEXT_SECTION (flag_pic) -extern int rx_float_compare_mode; - /* This is a version of REG_P that also returns TRUE for SUBREGs. */ #define RX_REG_P(rtl) (REG_P (rtl) || GET_CODE (rtl) == SUBREG) @@ -624,12 +622,4 @@ extern int rx_float_compare_mode; #define BRANCH_COST(SPEED,PREDICT) 1 #define REGISTER_MOVE_COST(MODE,FROM,TO) 2 -#define SELECT_CC_MODE(OP,X,Y) \ - (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT ? CC_ZSmode : \ - (GET_CODE (X) == PLUS || GET_CODE (X) == MINUS ? CC_ZSCmode : \ - (GET_CODE (X) == ABS ? CC_ZSOmode : \ - (GET_CODE (X) == AND || GET_CODE (X) == NOT || GET_CODE (X) == IOR \ - || GET_CODE (X) == XOR || GET_CODE (X) == ROTATE \ - || GET_CODE (X) == ROTATERT || GET_CODE (X) == ASHIFTRT \ - || GET_CODE (X) == LSHIFTRT || GET_CODE (X) == ASHIFT ? CC_ZSmode : \ - CCmode)))) +#define SELECT_CC_MODE(OP,X,Y) rx_select_cc_mode(OP, X, Y) diff --git a/gcc/config/rx/rx.md b/gcc/config/rx/rx.md index e0271d66322..d8cd66d63de 100644 --- a/gcc/config/rx/rx.md +++ b/gcc/config/rx/rx.md @@ -19,14 +19,6 @@ ;; <http://www.gnu.org/licenses/>. -;; This code iterator allows all branch instructions to -;; be generated from a single define_expand template. -(define_code_iterator most_cond [eq ne gt ge lt le gtu geu ltu leu - unordered ordered ]) - -;; Likewise, but only the ones that use Z or S. -(define_code_iterator zs_cond [eq ne gtu geu ltu leu ]) - ;; This code iterator is used for sign- and zero- extensions. (define_mode_iterator small_int_modes [(HI "") (QI "")]) @@ -150,6 +142,8 @@ (define_insn_reservation "throughput_18_latency_18" 1 (eq_attr "timings" "1818") "throughput*18") +;; ---------------------------------------------------------------------------- + ;; Comparisons ;; Note - we do not specify the two instructions necessary to perform @@ -160,250 +154,228 @@ (define_expand "cbranchsi4" [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(match_operand:SI 1 "register_operand") - (match_operand:SI 2 "rx_source_operand")]) - (label_ref (match_operand 3 "")) - (pc))) - ] - "" + (if_then_else + (match_operator 0 "comparison_operator" + [(match_operand:SI 1 "register_operand") + (match_operand:SI 2 "rx_source_operand")]) + (label_ref (match_operand 3 "")) + (pc)))] "" ) -(define_insn_and_split "*cbranchsi4_<code>" +(define_insn_and_split "*cbranchsi4" [(set (pc) - (if_then_else (most_cond (match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "rx_source_operand" "riQ")) - (label_ref (match_operand 2 "" "")) - (pc))) - ] + (if_then_else + (match_operator 3 "comparison_operator" + [(match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "rx_source_operand" "riQ")]) + (match_operand 2 "label_ref_operand" "") + (pc)))] "" "#" "reload_completed" [(const_int 0)] - " - /* We contstruct the split by hand as otherwise the JUMP_LABEL - attribute is not set correctly on the jump insn. */ - emit_insn (gen_cmpsi (operands[0], operands[1])); - - emit_jump_insn (gen_conditional_branch (operands[2], - gen_rtx_fmt_ee (<most_cond:CODE>, CCmode, - gen_rtx_REG (CCmode, CC_REG), const0_rtx))); - " -) +{ + rx_split_cbranch (CCmode, GET_CODE (operands[3]), + operands[0], operands[1], operands[2]); + DONE; +}) -;; ----------------------------------------------------------------------------- -;; These two are the canonical TST/branch insns. However, GCC -;; generates a wide variety of tst-like patterns, we catch those -;; below. -(define_insn_and_split "*tstbranchsi4_<code>" - [(set (pc) - (if_then_else (zs_cond (and:SI (match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "rx_source_operand" "riQ")) - (const_int 0)) - (label_ref (match_operand 2 "" "")) - (pc))) - ] - "" - "#" +(define_insn "*cmpsi" + [(set (reg:CC CC_REG) + (compare:CC (match_operand:SI 0 "register_operand" "r,r,r,r,r,r,r") + (match_operand:SI 1 "rx_source_operand" "r,Uint04,Int08,Sint16,Sint24,i,Q")))] "reload_completed" - [(const_int 0)] - " - emit_insn (gen_tstsi (operands[0], operands[1])); - - emit_jump_insn (gen_conditional_branch (operands[2], - gen_rtx_fmt_ee (<zs_cond:CODE>, CCmode, - gen_rtx_REG (CCmode, CC_REG), const0_rtx))); - " + "cmp\t%Q1, %0" + [(set_attr "timings" "11,11,11,11,11,11,33") + (set_attr "length" "2,2,3,4,5,6,5")] ) -;; Inverse of above -(define_insn_and_split "*tstbranchsi4r_<code>" +;; Canonical method for representing TST. +(define_insn_and_split "*cbranchsi4_tst" [(set (pc) - (if_then_else (zs_cond (and:SI (match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "rx_source_operand" "riQ")) - (const_int 0)) - (pc) - (label_ref (match_operand 2 "" "")))) - ] + (if_then_else + (match_operator 3 "rx_zs_comparison_operator" + [(and:SI (match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "rx_source_operand" "riQ")) + (const_int 0)]) + (match_operand 2 "label_ref_operand" "") + (pc)))] "" "#" "reload_completed" [(const_int 0)] - " - emit_insn (gen_tstsi (operands[0], operands[1])); - - emit_jump_insn (gen_conditional_branch (operands[2], - gen_rtx_fmt_ee (reverse_condition (<zs_cond:CODE>), CCmode, - gen_rtx_REG (CCmode, CC_REG), const0_rtx))); - " -) +{ + rx_split_cbranch (CC_ZSmode, GET_CODE (operands[3]), + XEXP (operands[3], 0), XEXP (operands[3], 1), + operands[2]); + DONE; +}) ;; Various other ways that GCC codes "var & const" - -(define_insn_and_split "*tstbranchsi4m_eq" - [(set (pc) - (if_then_else (eq (zero_extract:SI (match_operand:SI 0 "register_operand" "r") - (match_operand 1 "rx_constshift_operand" "i") - (match_operand 2 "rx_constshift_operand" "i")) - (const_int 0)) - (label_ref (match_operand 3 "" "")) - (pc))) - ] - "" - "#" - "" - [(set (pc) - (if_then_else (eq (and:SI (match_dup 0) - (match_dup 4)) - (const_int 0)) - (label_ref (match_dup 3)) - (pc))) - ] - "operands[4] = GEN_INT (((1 << INTVAL (operands[1]))-1) << INTVAL (operands[2]));" -) - -(define_insn_and_split "*tstbranchsi4m_ne" +(define_insn_and_split "*cbranchsi4_tst_ext" [(set (pc) - (if_then_else (ne (zero_extract:SI (match_operand:SI 0 "register_operand" "r") - (match_operand 1 "rx_constshift_operand" "i") - (match_operand 2 "rx_constshift_operand" "i")) - (const_int 0)) - (label_ref (match_operand 3 "" "")) - (pc))) - ] + (if_then_else + (match_operator 4 "rx_z_comparison_operator" + [(zero_extract:SI + (match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "rx_constshift_operand" "") + (match_operand:SI 2 "rx_constshift_operand" "")) + (const_int 0)]) + (match_operand 3 "label_ref_operand" "") + (pc)))] "" "#" - "" - [(set (pc) - (if_then_else (ne (and:SI (match_dup 0) - (match_dup 4)) - (const_int 0)) - (label_ref (match_dup 3)) - (pc))) - ] - "operands[4] = GEN_INT (((1 << INTVAL (operands[1]))-1) << INTVAL (operands[2]));" + "reload_completed" + [(const_int 0)] +{ + HOST_WIDE_INT mask; + rtx x; + + mask = 1; + mask <<= INTVAL (operands[1]); + mask -= 1; + mask <<= INTVAL (operands[2]); + x = gen_rtx_AND (SImode, operands[0], gen_int_mode (mask, SImode)); + + rx_split_cbranch (CC_ZSmode, GET_CODE (operands[4]), + x, const0_rtx, operands[3]); + DONE; +}) + +(define_insn "*tstsi" + [(set (reg:CC_ZS CC_REG) + (compare:CC_ZS + (and:SI (match_operand:SI 0 "register_operand" "r,r,r") + (match_operand:SI 1 "rx_source_operand" "r,i,Q")) + (const_int 0)))] + "reload_completed" + "tst\t%Q1, %0" + [(set_attr "timings" "11,11,33") + (set_attr "length" "3,7,6")] ) -;; ----------------------------------------------------------------------------- - (define_expand "cbranchsf4" [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(match_operand:SF 1 "register_operand") - (match_operand:SF 2 "rx_source_operand")]) - (label_ref (match_operand 3 "")) - (pc))) - ] + (if_then_else + (match_operator 0 "comparison_operator" + [(match_operand:SF 1 "register_operand") + (match_operand:SF 2 "register_operand")]) + (label_ref (match_operand 3 "")) + (pc)))] "ALLOW_RX_FPU_INSNS" - "" -) - -(define_insn_and_split "*cbranchsf4_<code>" +{ + enum rtx_code cmp1, cmp2; + + /* If the comparison needs swapping of operands, do that now. + Do not split the comparison in two yet. */ + if (rx_split_fp_compare (GET_CODE (operands[0]), &cmp1, &cmp2)) + { + rtx op1, op2; + + if (cmp2 != UNKNOWN) + { + gcc_assert (cmp1 == UNORDERED); + if (cmp2 == GT) + cmp1 = UNGT; + else if (cmp2 == LE) + cmp1 = UNLE; + else + gcc_unreachable (); + } + + op1 = operands[2]; + op2 = operands[1]; + operands[0] = gen_rtx_fmt_ee (cmp1, VOIDmode, op1, op2); + operands[1] = op1; + operands[2] = op2; + } +}) + +(define_insn_and_split "*cbranchsf4" [(set (pc) - (if_then_else (most_cond (match_operand:SF 0 "register_operand" "r") - (match_operand:SF 1 "rx_source_operand" "rFiQ")) - (label_ref (match_operand 2 "" "")) - (pc))) - ] + (if_then_else + (match_operator 3 "rx_fp_comparison_operator" + [(match_operand:SF 0 "register_operand" "r") + (match_operand:SF 1 "rx_source_operand" "rFiQ")]) + (match_operand 2 "label_ref_operand" "") + (pc)))] "ALLOW_RX_FPU_INSNS" "#" "&& reload_completed" [(const_int 0)] - " - /* We contstruct the split by hand as otherwise the JUMP_LABEL - attribute is not set correctly on the jump insn. */ - emit_insn (gen_cmpsf (operands[0], operands[1])); - - emit_jump_insn (gen_conditional_branch (operands[2], - gen_rtx_fmt_ee (<most_cond:CODE>, CCmode, - gen_rtx_REG (CCmode, CC_REG), const0_rtx))); - " -) - -(define_insn "tstsi" - [(set (reg:CC_ZS CC_REG) - (compare:CC_ZS (and:SI (match_operand:SI 0 "register_operand" "r,r,r") - (match_operand:SI 1 "rx_source_operand" "r,i,Q")) - (const_int 0)))] - "" - { - rx_float_compare_mode = false; - return "tst\t%Q1, %0"; - } - [(set_attr "timings" "11,11,33") - (set_attr "length" "3,7,6")] -) - -(define_insn "cmpsi" - [(set (reg:CC CC_REG) - (compare:CC (match_operand:SI 0 "register_operand" "r,r,r,r,r,r,r") - (match_operand:SI 1 "rx_source_operand" "r,Uint04,Int08,Sint16,Sint24,i,Q")))] - "" - { - rx_float_compare_mode = false; - if (rx_compare_redundant (insn)) - return "; Compare Eliminated: cmp %Q1, %0"; - return "cmp\t%Q1, %0"; - } - [(set_attr "timings" "11,11,11,11,11,11,33") - (set_attr "length" "2,2,3,4,5,6,5")] -) - -;; ??? g++.dg/eh/080514-1.C to see this happen. -(define_insn "cmpsf" - [(set (reg:CC_ZSO CC_REG) - (compare:CC_ZSO (match_operand:SF 0 "register_operand" "r,r,r") - (match_operand:SF 1 "rx_source_operand" "r,iF,Q")))] - "ALLOW_RX_FPU_INSNS" - { - rx_float_compare_mode = true; - return "fcmp\t%1, %0"; - } +{ + enum rtx_code cmp0, cmp1, cmp2; + rtx flags, lab1, lab2, over, x; + bool swap; + + cmp0 = GET_CODE (operands[3]); + swap = rx_split_fp_compare (cmp0, &cmp1, &cmp2); + gcc_assert (!swap); + + flags = gen_rtx_REG (CC_Fmode, CC_REG); + x = gen_rtx_COMPARE (CC_Fmode, operands[0], operands[1]); + x = gen_rtx_SET (VOIDmode, flags, x); + emit_insn (x); + + over = NULL; + lab1 = lab2 = operands[2]; + + /* The one case of LTGT needs to be split into cmp1 && cmp2. */ + if (cmp0 == LTGT) + { + over = gen_label_rtx (); + lab1 = gen_rtx_LABEL_REF (VOIDmode, over); + cmp1 = reverse_condition_maybe_unordered (cmp1); + } + + /* Otherwise we split into cmp1 || cmp2. */ + x = gen_rtx_fmt_ee (cmp1, VOIDmode, flags, const0_rtx); + x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, lab1, pc_rtx); + x = gen_rtx_SET (VOIDmode, pc_rtx, x); + emit_jump_insn (x); + + if (cmp2 != UNKNOWN) + { + x = gen_rtx_fmt_ee (cmp2, VOIDmode, flags, const0_rtx); + x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, lab2, pc_rtx); + x = gen_rtx_SET (VOIDmode, pc_rtx, x); + emit_jump_insn (x); + } + + if (over) + emit_label (over); + DONE; +}) + +(define_insn "*cmpsf" + [(set (reg:CC_F CC_REG) + (compare:CC_F + (match_operand:SF 0 "register_operand" "r,r,r") + (match_operand:SF 1 "rx_source_operand" "r,iF,Q")))] + "ALLOW_RX_FPU_INSNS && reload_completed" + "fcmp\t%1, %0" [(set_attr "timings" "11,11,33") (set_attr "length" "3,7,5")] ) ;; Flow Control Instructions: -(define_expand "b<code>" +(define_insn "*conditional_branch" [(set (pc) - (if_then_else (most_cond (reg:CC CC_REG) (const_int 0)) - (label_ref (match_operand 0)) - (pc)))] - "" + (if_then_else + (match_operator 1 "comparison_operator" + [(reg CC_REG) (const_int 0)]) + (label_ref (match_operand 0 "" "")) + (pc)))] "" -) - -(define_insn "conditional_branch" - [(set (pc) - (if_then_else (match_operator 1 "comparison_operator" - [(reg:CC CC_REG) (const_int 0)]) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - { - return rx_gen_cond_branch_template (operands[1], false); - } + "b%B1\t%0" [(set_attr "length" "8") ;; This length is wrong, but it is ;; too hard to compute statically. (set_attr "timings" "33")] ;; The timing assumes that the branch is taken. ) -(define_insn "*reveresed_conditional_branch" - [(set (pc) - (if_then_else (match_operator 1 "comparison_operator" - [(reg:CC CC_REG) (const_int 0)]) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - { - return rx_gen_cond_branch_template (operands[1], true); - } - [(set_attr "length" "8") ;; This length is wrong, but it is - ;; too hard to compute statically. - (set_attr "timings" "33")] ;; The timing assumes that the branch is taken. -) +;; ---------------------------------------------------------------------------- (define_insn "jump" [(set (pc) @@ -457,9 +429,9 @@ (define_insn "pop_and_return" [(match_parallel 1 "rx_rtsd_vector" - [(set:SI (reg:SI SP_REG) - (plus:SI (reg:SI SP_REG) - (match_operand:SI 0 "const_int_operand" "n")))])] + [(set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) + (match_operand:SI 0 "const_int_operand" "n")))])] "reload_completed" { rx_emit_stack_popm (operands, false); @@ -684,11 +656,11 @@ ) (define_insn "stack_push" - [(set:SI (reg:SI SP_REG) - (minus:SI (reg:SI SP_REG) - (const_int 4))) - (set:SI (mem:SI (reg:SI SP_REG)) - (match_operand:SI 0 "register_operand" "r"))] + [(set (reg:SI SP_REG) + (minus:SI (reg:SI SP_REG) + (const_int 4))) + (set (mem:SI (reg:SI SP_REG)) + (match_operand:SI 0 "register_operand" "r"))] "" "push.l\t%0" [(set_attr "length" "2")] @@ -696,9 +668,9 @@ (define_insn "stack_pushm" [(match_parallel 1 "rx_store_multiple_vector" - [(set:SI (reg:SI SP_REG) - (minus:SI (reg:SI SP_REG) - (match_operand:SI 0 "const_int_operand" "n")))])] + [(set (reg:SI SP_REG) + (minus:SI (reg:SI SP_REG) + (match_operand:SI 0 "const_int_operand" "n")))])] "reload_completed" { rx_emit_stack_pushm (operands); @@ -709,11 +681,11 @@ ) (define_insn "stack_pop" - [(set:SI (match_operand:SI 0 "register_operand" "=r") - (mem:SI (reg:SI SP_REG))) - (set:SI (reg:SI SP_REG) - (plus:SI (reg:SI SP_REG) - (const_int 4)))] + [(set (match_operand:SI 0 "register_operand" "=r") + (mem:SI (reg:SI SP_REG))) + (set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) + (const_int 4)))] "" "pop\t%0" [(set_attr "length" "2") @@ -722,9 +694,9 @@ (define_insn "stack_popm" [(match_parallel 1 "rx_load_multiple_vector" - [(set:SI (reg:SI SP_REG) - (plus:SI (reg:SI SP_REG) - (match_operand:SI 0 "const_int_operand" "n")))])] + [(set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) + (match_operand:SI 0 "const_int_operand" "n")))])] "reload_completed" { rx_emit_stack_popm (operands, true); @@ -734,79 +706,230 @@ (set_attr "timings" "45")] ;; The timing is a guesstimate average timing. ) -;; FIXME: Add memory destination options ? -(define_insn "cstoresi4" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r") +(define_insn_and_split "cstoresi4" + [(set (match_operand:SI 0 "register_operand" "=r") (match_operator:SI 1 "comparison_operator" - [(match_operand:SI 2 "register_operand" "r,r,r,r,r,r,r") - (match_operand:SI 3 "rx_source_operand" "r,Uint04,Int08,Sint16,Sint24,i,Q")])) - (clobber (reg:CC CC_REG))] ;; Because the cc flags are set based on comparing ops 2 & 3 not the value in op 0. + [(match_operand:SI 2 "register_operand" "r") + (match_operand:SI 3 "rx_source_operand" "riQ")])) + (clobber (reg:CC CC_REG))] "" - { - rx_float_compare_mode = false; - return "cmp\t%Q3, %Q2\n\tsc%B1.L\t%0"; - } - [(set_attr "timings" "22,22,22,22,22,22,44") - (set_attr "length" "5,5,6,7,8,9,8")] + "#" + "reload_completed" + [(const_int 0)] +{ + rtx flags, x; + + flags = gen_rtx_REG (CCmode, CC_REG); + x = gen_rtx_COMPARE (CCmode, operands[2], operands[3]); + x = gen_rtx_SET (VOIDmode, flags, x); + emit_insn (x); + + x = gen_rtx_fmt_ee (GET_CODE (operands[1]), SImode, flags, const0_rtx); + x = gen_rtx_SET (VOIDmode, operands[0], x); + emit_insn (x); + DONE; +}) + +(define_insn "*sccc" + [(set (match_operand:SI 0 "register_operand" "=r") + (match_operator:SI 1 "comparison_operator" + [(reg CC_REG) (const_int 0)]))] + "reload_completed" + "sc%B1.L\t%0" + [(set_attr "length" "3")] ) +(define_expand "cstoresf4" + [(parallel [(set (match_operand:SI 0 "register_operand" "") + (match_operator:SI 1 "comparison_operator" + [(match_operand:SF 2 "register_operand" "") + (match_operand:SF 3 "register_operand" "")])) + (clobber (match_scratch:SI 4))])] + "ALLOW_RX_FPU_INSNS" +{ + enum rtx_code cmp1, cmp2; + + /* If the comparison needs swapping of operands, do that now. + Do not split the comparison in two yet. */ + if (rx_split_fp_compare (GET_CODE (operands[0]), &cmp1, &cmp2)) + { + rtx op2, op3; + + if (cmp2 != UNKNOWN) + { + gcc_assert (cmp1 == UNORDERED); + if (cmp2 == GT) + cmp1 = UNGT; + else if (cmp2 == LE) + cmp1 = UNLE; + else + gcc_unreachable (); + } + + op2 = operands[3]; + op3 = operands[2]; + operands[0] = gen_rtx_fmt_ee (cmp1, VOIDmode, op2, op3); + operands[2] = op2; + operands[3] = op3; + } +}) + +(define_insn_and_split "*cstoresf4" + [(set (match_operand:SI 0 "register_operand" "=r") + (match_operator:SI 4 "rx_fp_comparison_operator" + [(match_operand:SF 2 "register_operand" "r") + (match_operand:SF 3 "rx_source_operand" "rFiQ")])) + (clobber (match_scratch:SI 1 "=r"))] + "ALLOW_RX_FPU_INSNS" + "#" + "reload_completed" + [(const_int 0)] +{ + enum rtx_code cmp0, cmp1, cmp2; + rtx flags, x; + bool swap; + + cmp0 = GET_CODE (operands[4]); + swap = rx_split_fp_compare (cmp0, &cmp1, &cmp2); + gcc_assert (!swap); + + flags = gen_rtx_REG (CC_Fmode, CC_REG); + x = gen_rtx_COMPARE (CC_Fmode, operands[2], operands[3]); + x = gen_rtx_SET (VOIDmode, flags, x); + emit_insn (x); + + x = gen_rtx_fmt_ee (cmp1, SImode, flags, const0_rtx); + x = gen_rtx_SET (VOIDmode, operands[0], x); + emit_insn (x); + + if (cmp0 == LTGT) + { + /* The one case of LTGT needs to be split into ORDERED && NE. */ + x = gen_rtx_fmt_ee (EQ, VOIDmode, flags, const0_rtx); + x = gen_rtx_IF_THEN_ELSE (SImode, x, const0_rtx, operands[0]); + x = gen_rtx_SET (VOIDmode, operands[0], x); + emit_insn (x); + } + else if (cmp2 == EQ || cmp2 == NE) + { + /* Oring the two flags can be performed with a movcc operation. */ + x = gen_rtx_fmt_ee (cmp2, VOIDmode, flags, const0_rtx); + x = gen_rtx_IF_THEN_ELSE (SImode, x, const1_rtx, operands[0]); + x = gen_rtx_SET (VOIDmode, operands[0], x); + emit_insn (x); + } + else if (cmp2 != UNKNOWN) + { + /* We can't use movcc, but need to or in another compare. + Do this by storing the second operation into the scratch. */ + x = gen_rtx_fmt_ee (cmp2, SImode, flags, const0_rtx); + x = gen_rtx_SET (VOIDmode, operands[1], x); + emit_insn (x); + + emit_insn (gen_iorsi3 (operands[0], operands[0], operands[1])); + } + DONE; +}) + (define_expand "movsicc" [(parallel [(set (match_operand:SI 0 "register_operand") (if_then_else:SI (match_operand:SI 1 "comparison_operator") (match_operand:SI 2 "nonmemory_operand") - (match_operand:SI 3 "immediate_operand"))) - (clobber (reg:CC CC_REG))])] ;; See cstoresi4 + (match_operand:SI 3 "nonmemory_operand"))) + (clobber (reg:CC CC_REG))])] "" - { - if (GET_CODE (operands[1]) != EQ && GET_CODE (operands[1]) != NE) - FAIL; - if (! CONST_INT_P (operands[3])) - FAIL; - } +{ + /* ??? Support other conditions via cstore into a temporary? */ + if (GET_CODE (operands[1]) != EQ && GET_CODE (operands[1]) != NE) + FAIL; + /* One operand must be a constant. */ + if (!CONSTANT_P (operands[2]) && !CONSTANT_P (operands[3])) + FAIL; +}) + +(define_insn_and_split "*movsicc" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (if_then_else:SI + (match_operator 5 "rx_z_comparison_operator" + [(match_operand:SI 3 "register_operand" "r,r") + (match_operand:SI 4 "rx_source_operand" "riQ,riQ")]) + (match_operand:SI 1 "nonmemory_operand" "i,ri") + (match_operand:SI 2 "nonmemory_operand" "ri,i"))) + (clobber (reg:CC CC_REG))] + "CONSTANT_P (operands[1]) || CONSTANT_P (operands[2])" + "#" + "&& reload_completed" + [(const_int 0)] +{ + rtx x, flags, op0, op1, op2; + enum rtx_code cmp_code; + + flags = gen_rtx_REG (CCmode, CC_REG); + x = gen_rtx_COMPARE (CCmode, operands[3], operands[4]); + emit_insn (gen_rtx_SET (VOIDmode, flags, x)); + + cmp_code = GET_CODE (operands[5]); + op0 = operands[0]; + op1 = operands[1]; + op2 = operands[2]; + + /* If OP2 is the constant, reverse the sense of the move. */ + if (!CONSTANT_P (operands[1])) + { + x = op1, op1 = op2, op2 = x; + cmp_code = reverse_condition (cmp_code); + } + + /* If OP2 does not match the output, copy it into place. We have allowed + these alternatives so that the destination can legitimately be one of + the comparison operands without increasing register pressure. */ + if (!rtx_equal_p (op0, op2)) + emit_move_insn (op0, op2); + + x = gen_rtx_fmt_ee (cmp_code, VOIDmode, flags, const0_rtx); + x = gen_rtx_IF_THEN_ELSE (SImode, x, op1, op0); + emit_insn (gen_rtx_SET (VOIDmode, op0, x)); + DONE; +}) + +(define_insn "*stcc" + [(set (match_operand:SI 0 "register_operand" "+r,r,r,r") + (if_then_else:SI + (match_operator 2 "rx_z_comparison_operator" + [(reg CC_REG) (const_int 0)]) + (match_operand:SI 1 "immediate_operand" "Sint08,Sint16,Sint24,i") + (match_dup 0)))] + "reload_completed" +{ + if (GET_CODE (operands[2]) == EQ) + return "stz\t%1, %0"; + else + return "stnz\t%1, %0"; +} + [(set_attr "length" "4,5,6,7")] ) -(define_insn "*movsieq" - [(set (match_operand:SI 0 "register_operand" "=r,r,r") - (if_then_else:SI (eq (match_operand:SI 3 "register_operand" "r,r,r") - (match_operand:SI 4 "rx_source_operand" "riQ,riQ,riQ")) - (match_operand:SI 1 "nonmemory_operand" "0,i,r") - (match_operand:SI 2 "immediate_operand" "i,i,i"))) - (clobber (reg:CC CC_REG))] ;; See cstoresi4 - "" - "@ - cmp\t%Q4, %Q3\n\tstnz\t%2, %0 - cmp\t%Q4, %Q3\n\tmov.l\t%2, %0\n\tstz\t%1, %0 - cmp\t%Q4, %Q3\n\tmov.l\t%1, %0\n\tstnz\t%2, %0" - [(set_attr "length" "13,19,15") - (set_attr "timings" "22,33,33")] -) +;; Arithmetic Instructions -(define_insn "*movsine" - [(set (match_operand:SI 0 "register_operand" "=r,r,r") - (if_then_else:SI (ne (match_operand:SI 3 "register_operand" "r,r,r") - (match_operand:SI 4 "rx_source_operand" "riQ,riQ,riQ")) - (match_operand:SI 1 "nonmemory_operand" "0,i,r") - (match_operand:SI 2 "immediate_operand" "i,i,i"))) - (clobber (reg:CC CC_REG))] ;; See cstoresi4 +(define_insn "abssi2" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (abs:SI (match_operand:SI 1 "register_operand" "0,r"))) + (clobber (reg:CC CC_REG))] "" "@ - cmp\t%Q4, %Q3\n\tstz\t%2, %0 - cmp\t%Q4, %Q3\n\tmov.l\t%2, %0\n\tstnz\t%1, %0 - cmp\t%Q4, %Q3\n\tmov.l\t%1, %0\n\tstz\t%2, %0" - [(set_attr "length" "13,19,15") - (set_attr "timings" "22,33,33")] + abs\t%0 + abs\t%1, %0" + [(set_attr "length" "2,3")] ) -;; Arithmetic Instructions - -(define_insn "abssi2" +(define_insn "*abssi2_flags" [(set (match_operand:SI 0 "register_operand" "=r,r") (abs:SI (match_operand:SI 1 "register_operand" "0,r"))) - (set (reg:CC_ZSO CC_REG) - (compare:CC_ZSO (abs:SI (match_dup 1)) - (const_int 0)))] - "" + (set (reg CC_REG) + (compare (abs:SI (match_dup 1)) + (const_int 0)))] + "reload_completed && rx_match_ccmode (insn, CC_ZSOmode)" "@ abs\t%0 abs\t%1, %0" @@ -817,9 +940,7 @@ [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r,r,r,r,r,r") (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,0,r,r,r,r,r,r,0") (match_operand:SI 2 "rx_source_operand" "r,Uint04,NEGint4,Sint08,Sint16,Sint24,i,0,r,Sint08,Sint16,Sint24,i,Q"))) - (set (reg:CC_ZSC CC_REG) ;; See subsi3 - (compare:CC_ZSC (plus:SI (match_dup 1) (match_dup 2)) - (const_int 0)))] + (clobber (reg:CC CC_REG))] "" "@ add\t%2, %0 @@ -840,27 +961,160 @@ (set_attr "length" "2,2,2,3,4,5,6,2,3,3,4,5,6,5")] ) -(define_insn "adddi3" - [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r") - (plus:DI (match_operand:DI 1 "register_operand" "%0,0,0,0,0,0") - (match_operand:DI 2 "rx_source_operand" - "r,Sint08,Sint16,Sint24,i,Q"))) - (set (reg:CC_ZSC CC_REG) ;; See subsi3 - (compare:CC_ZSC (plus:DI (match_dup 1) (match_dup 2)) - (const_int 0)))] - "" - "add\t%L2, %L0\n\tadc\t%H2, %H0" - [(set_attr "timings" "22,22,22,22,22,44") - (set_attr "length" "5,7,9,11,13,11")] +(define_insn "*addsi3_flags" + [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r,r,r,r,r,r") + (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,0,r,r,r,r,r,r,0") + (match_operand:SI 2 "rx_source_operand" "r,Uint04,NEGint4,Sint08,Sint16,Sint24,i,0,r,Sint08,Sint16,Sint24,i,Q"))) + (set (reg CC_REG) + (compare (plus:SI (match_dup 1) (match_dup 2)) + (const_int 0)))] + "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)" + "@ + add\t%2, %0 + add\t%2, %0 + sub\t%N2, %0 + add\t%2, %0 + add\t%2, %0 + add\t%2, %0 + add\t%2, %0 + add\t%1, %0 + add\t%2, %1, %0 + add\t%2, %1, %0 + add\t%2, %1, %0 + add\t%2, %1, %0 + add\t%2, %1, %0 + add\t%Q2, %0" + [(set_attr "timings" "11,11,11,11,11,11,11,11,11,11,11,11,11,33") + (set_attr "length" "2,2,2,3,4,5,6,2,3,3,4,5,6,5")] ) +;; A helper to expand the above with the CC_MODE filled in. +(define_expand "addsi3_flags" + [(parallel [(set (match_operand:SI 0 "register_operand") + (plus:SI (match_operand:SI 1 "register_operand") + (match_operand:SI 2 "rx_source_operand"))) + (set (reg:CC_ZSC CC_REG) + (compare:CC_ZSC (plus:SI (match_dup 1) (match_dup 2)) + (const_int 0)))])] +) + +(define_insn "adc_internal" + [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r") + (plus:SI + (plus:SI + (ltu:SI (reg:CC CC_REG) (const_int 0)) + (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")) + (match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q"))) + (clobber (reg:CC CC_REG))] + "reload_completed" + "adc %2,%0" + [(set_attr "timings" "11,11,11,11,11,33") + (set_attr "length" "3,4,5,6,7,6")] +) + +(define_insn "*adc_flags" + [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r") + (plus:SI + (plus:SI + (ltu:SI (reg:CC CC_REG) (const_int 0)) + (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")) + (match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q"))) + (set (reg CC_REG) + (compare + (plus:SI + (plus:SI + (ltu:SI (reg:CC CC_REG) (const_int 0)) + (match_dup 1)) + (match_dup 2)) + (const_int 0)))] + "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)" + "adc %2,%0" + [(set_attr "timings" "11,11,11,11,11,33") + (set_attr "length" "3,4,5,6,7,6")] +) + +(define_expand "adddi3" + [(set (match_operand:DI 0 "register_operand" "") + (plus:DI (match_operand:DI 1 "register_operand" "") + (match_operand:DI 2 "rx_source_operand" "")))] + "" +{ + rtx op0l, op0h, op1l, op1h, op2l, op2h; + + op0l = gen_lowpart (SImode, operands[0]); + op1l = gen_lowpart (SImode, operands[1]); + op2l = gen_lowpart (SImode, operands[2]); + op0h = gen_highpart (SImode, operands[0]); + op1h = gen_highpart (SImode, operands[1]); + op2h = gen_highpart_mode (SImode, DImode, operands[2]); + + emit_insn (gen_adddi3_internal (op0l, op0h, op1l, op2l, op1h, op2h)); + DONE; +}) + +(define_insn_and_split "adddi3_internal" + [(set (match_operand:SI 0 "register_operand" "=r") + (plus:SI (match_operand:SI 2 "register_operand" "r") + (match_operand:SI 3 "rx_source_operand" "riQ"))) + (set (match_operand:SI 1 "register_operand" "=r") + (plus:SI + (plus:SI + (ltu:SI (plus:SI (match_dup 2) (match_dup 3)) (match_dup 2)) + (match_operand:SI 4 "register_operand" "%1")) + (match_operand:SI 5 "rx_source_operand" "riQ"))) + (clobber (match_scratch:SI 6 "=&r")) + (clobber (reg:CC CC_REG))] + "" + "#" + "reload_completed" + [(const_int 0)] +{ + rtx op0l = operands[0]; + rtx op0h = operands[1]; + rtx op1l = operands[2]; + rtx op2l = operands[3]; + rtx op1h = operands[4]; + rtx op2h = operands[5]; + rtx scratch = operands[6]; + rtx x; + + if (reg_overlap_mentioned_p (op0l, op1h)) + { + emit_move_insn (scratch, op0l); + op1h = scratch; + if (reg_overlap_mentioned_p (op0l, op2h)) + op2h = scratch; + } + else if (reg_overlap_mentioned_p (op0l, op2h)) + { + emit_move_insn (scratch, op0l); + op2h = scratch; + } + + if (rtx_equal_p (op0l, op1l)) + ; + else if (rtx_equal_p (op0l, op2l)) + x = op1l, op1l = op2l, op2l = x; + emit_insn (gen_addsi3_flags (op0l, op1l, op2l)); + + if (rtx_equal_p (op0h, op1h)) + ; + else if (rtx_equal_p (op0h, op2h)) + x = op1h, op1h = op2h, op2h = x; + else + { + emit_move_insn (op0h, op1h); + op1h = op0h; + } + emit_insn (gen_adc_internal (op0h, op1h, op2h)); + DONE; +}) + (define_insn "andsi3" [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r") (and:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r,0") (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q"))) - (set (reg:CC_ZS CC_REG) - (compare:CC_ZS (and:SI (match_dup 1) (match_dup 2)) - (const_int 0)))] + (clobber (reg:CC CC_REG))] "" "@ and\t%2, %0 @@ -876,9 +1130,31 @@ (set_attr "length" "2,2,3,4,5,6,2,5,5")] ) +(define_insn "*andsi3_flags" + [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r") + (and:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r,0") + (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q"))) + (set (reg CC_REG) + (compare (and:SI (match_dup 1) (match_dup 2)) + (const_int 0)))] + "reload_completed && rx_match_ccmode (insn, CC_ZSmode)" + "@ + and\t%2, %0 + and\t%2, %0 + and\t%2, %0 + and\t%2, %0 + and\t%2, %0 + and\t%2, %0 + and\t%1, %0 + and\t%2, %1, %0 + and\t%Q2, %0" + [(set_attr "timings" "11,11,11,11,11,11,11,33,33") + (set_attr "length" "2,2,3,4,5,6,2,5,5")] +) + ;; Byte swap (single 32-bit value). (define_insn "bswapsi2" - [(set (match_operand:SI 0 "register_operand" "+r") + [(set (match_operand:SI 0 "register_operand" "=r") (bswap:SI (match_operand:SI 1 "register_operand" "r")))] "" "revl\t%1, %0" @@ -887,7 +1163,7 @@ ;; Byte swap (single 16-bit value). Note - we ignore the swapping of the high 16-bits. (define_insn "bswaphi2" - [(set (match_operand:HI 0 "register_operand" "+r") + [(set (match_operand:HI 0 "register_operand" "=r") (bswap:HI (match_operand:HI 1 "register_operand" "r")))] "" "revw\t%1, %0" @@ -995,12 +1271,23 @@ (define_insn "negsi2" [(set (match_operand:SI 0 "register_operand" "=r,r") (neg:SI (match_operand:SI 1 "register_operand" "0,r"))) - (set (reg:CC CC_REG) - (compare:CC (neg:SI (match_dup 1)) - (const_int 0)))] - ;; The NEG instruction does not comply with -fwrapv semantics. - ;; See gcc.c-torture/execute/pr22493-1.c for an example of this. - "! flag_wrapv" + (clobber (reg:CC CC_REG))] + "" + "@ + neg\t%0 + neg\t%1, %0" + [(set_attr "length" "2,3")] +) + +;; Note that the O and C flags are not set as per a normal compare, +;; and thus are unusable in that context. +(define_insn "*negsi2_flags" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (neg:SI (match_operand:SI 1 "register_operand" "0,r"))) + (set (reg CC_REG) + (compare (neg:SI (match_dup 1)) + (const_int 0)))] + "reload_completed && rx_match_ccmode (insn, CC_ZSmode)" "@ neg\t%0 neg\t%1, %0" @@ -1010,9 +1297,7 @@ (define_insn "one_cmplsi2" [(set (match_operand:SI 0 "register_operand" "=r,r") (not:SI (match_operand:SI 1 "register_operand" "0,r"))) - (set (reg:CC_ZS CC_REG) - (compare:CC_ZS (not:SI (match_dup 1)) - (const_int 0)))] + (clobber (reg:CC CC_REG))] "" "@ not\t%0 @@ -1020,13 +1305,24 @@ [(set_attr "length" "2,3")] ) +(define_insn "*one_cmplsi2_flags" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (not:SI (match_operand:SI 1 "register_operand" "0,r"))) + (set (reg CC_REG) + (compare (not:SI (match_dup 1)) + (const_int 0)))] + "reload_completed && rx_match_ccmode (insn, CC_ZSmode)" + "@ + not\t%0 + not\t%1, %0" + [(set_attr "length" "2,3")] +) + (define_insn "iorsi3" [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r") (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r,0") (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q"))) - (set (reg:CC_ZS CC_REG) - (compare:CC_ZS (ior:SI (match_dup 1) (match_dup 2)) - (const_int 0)))] + (clobber (reg:CC CC_REG))] "" "@ or\t%2, %0 @@ -1042,37 +1338,77 @@ (set_attr "length" "2,2,3,4,5,6,2,3,5")] ) +(define_insn "*iorsi3_flags" + [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r") + (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r,0") + (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q"))) + (set (reg CC_REG) + (compare (ior:SI (match_dup 1) (match_dup 2)) + (const_int 0)))] + "reload_completed && rx_match_ccmode (insn, CC_ZSmode)" + "@ + or\t%2, %0 + or\t%2, %0 + or\t%2, %0 + or\t%2, %0 + or\t%2, %0 + or\t%Q2, %0 + or\t%1, %0 + or\t%2, %1, %0 + or\t%Q2, %0" + [(set_attr "timings" "11,11,11,11,11,11,11,11,33") + (set_attr "length" "2,2,3,4,5,6,2,3,5")] +) + (define_insn "rotlsi3" [(set (match_operand:SI 0 "register_operand" "=r") (rotate:SI (match_operand:SI 1 "register_operand" "0") (match_operand:SI 2 "rx_shift_operand" "rn"))) - (set (reg:CC_ZS CC_REG) - (compare:CC_ZS (rotate:SI (match_dup 1) (match_dup 2)) - (const_int 0)))] + (clobber (reg:CC CC_REG))] "" "rotl\t%2, %0" [(set_attr "length" "3")] ) +(define_insn "*rotlsi3_flags" + [(set (match_operand:SI 0 "register_operand" "=r") + (rotate:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "rx_shift_operand" "rn"))) + (set (reg CC_REG) + (compare (rotate:SI (match_dup 1) (match_dup 2)) + (const_int 0)))] + "reload_completed && rx_match_ccmode (insn, CC_ZSmode)" + "rotl\t%2, %0" + [(set_attr "length" "3")] +) + (define_insn "rotrsi3" [(set (match_operand:SI 0 "register_operand" "=r") (rotatert:SI (match_operand:SI 1 "register_operand" "0") (match_operand:SI 2 "rx_shift_operand" "rn"))) - (set (reg:CC_ZS CC_REG) - (compare:CC_ZS (rotatert:SI (match_dup 1) (match_dup 2)) - (const_int 0)))] + (clobber (reg:CC CC_REG))] "" "rotr\t%2, %0" [(set_attr "length" "3")] ) +(define_insn "*rotrsi3_flags" + [(set (match_operand:SI 0 "register_operand" "=r") + (rotatert:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "rx_shift_operand" "rn"))) + (set (reg CC_REG) + (compare (rotatert:SI (match_dup 1) (match_dup 2)) + (const_int 0)))] + "reload_completed && rx_match_ccmode (insn, CC_ZSmode)" + "rotr\t%2, %0" + [(set_attr "length" "3")] +) + (define_insn "ashrsi3" [(set (match_operand:SI 0 "register_operand" "=r,r,r") (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r") (match_operand:SI 2 "rx_shift_operand" "r,n,n"))) - (set (reg:CC_ZS CC_REG) - (compare:CC_ZS (ashiftrt:SI (match_dup 1) (match_dup 2)) - (const_int 0)))] + (clobber (reg:CC CC_REG))] "" "@ shar\t%2, %0 @@ -1081,13 +1417,26 @@ [(set_attr "length" "3,2,3")] ) +(define_insn "*ashrsi3_flags" + [(set (match_operand:SI 0 "register_operand" "=r,r,r") + (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r") + (match_operand:SI 2 "rx_shift_operand" "r,n,n"))) + (set (reg CC_REG) + (compare (ashiftrt:SI (match_dup 1) (match_dup 2)) + (const_int 0)))] + "reload_completed && rx_match_ccmode (insn, CC_ZSmode)" + "@ + shar\t%2, %0 + shar\t%2, %0 + shar\t%2, %1, %0" + [(set_attr "length" "3,2,3")] +) + (define_insn "lshrsi3" [(set (match_operand:SI 0 "register_operand" "=r,r,r") (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r") (match_operand:SI 2 "rx_shift_operand" "r,n,n"))) - (set (reg:CC_ZS CC_REG) - (compare:CC_ZS (lshiftrt:SI (match_dup 1) (match_dup 2)) - (const_int 0)))] + (clobber (reg:CC CC_REG))] "" "@ shlr\t%2, %0 @@ -1096,13 +1445,26 @@ [(set_attr "length" "3,2,3")] ) +(define_insn "*lshrsi3_flags" + [(set (match_operand:SI 0 "register_operand" "=r,r,r") + (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r") + (match_operand:SI 2 "rx_shift_operand" "r,n,n"))) + (set (reg CC_REG) + (compare (lshiftrt:SI (match_dup 1) (match_dup 2)) + (const_int 0)))] + "reload_completed && rx_match_ccmode (insn, CC_ZSmode)" + "@ + shlr\t%2, %0 + shlr\t%2, %0 + shlr\t%2, %1, %0" + [(set_attr "length" "3,2,3")] +) + (define_insn "ashlsi3" [(set (match_operand:SI 0 "register_operand" "=r,r,r") (ashift:SI (match_operand:SI 1 "register_operand" "0,0,r") (match_operand:SI 2 "rx_shift_operand" "r,n,n"))) - (set (reg:CC_ZS CC_REG) - (compare:CC_ZS (ashift:SI (match_dup 1) (match_dup 2)) - (const_int 0)))] + (clobber (reg:CC CC_REG))] "" "@ shll\t%2, %0 @@ -1111,16 +1473,57 @@ [(set_attr "length" "3,2,3")] ) +(define_insn "*ashlsi3_flags" + [(set (match_operand:SI 0 "register_operand" "=r,r,r") + (ashift:SI (match_operand:SI 1 "register_operand" "0,0,r") + (match_operand:SI 2 "rx_shift_operand" "r,n,n"))) + (set (reg CC_REG) + (compare (ashift:SI (match_dup 1) (match_dup 2)) + (const_int 0)))] + "reload_completed && rx_match_ccmode (insn, CC_ZSmode)" + "@ + shll\t%2, %0 + shll\t%2, %0 + shll\t%2, %1, %0" + [(set_attr "length" "3,2,3")] +) + +;; Saturate to 32-bits +(define_insn_and_split "ssaddsi3" + [(set (match_operand:SI 0 "register_operand" "=r") + (ss_plus:SI (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "rx_source_operand" "riQ"))) + (clobber (reg:CC CC_REG))] + "" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) + (plus:SI (match_dup 1) (match_dup 2))) + (set (reg:CC_ZSC CC_REG) + (compare:CC_ZSC + (plus:SI (match_dup 1) (match_dup 2)) + (const_int 0)))]) + (set (match_dup 0) + (unspec:SI [(match_dup 0) (reg:CC CC_REG)] + UNSPEC_BUILTIN_SAT))] + "" +) + +(define_insn "*sat" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(match_operand:SI 1 "register_operand" "0") + (reg:CC CC_REG)] + UNSPEC_BUILTIN_SAT))] + "reload_completed" + "sat\t%0" + [(set_attr "length" "2")] +) + (define_insn "subsi3" [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r") (minus:SI (match_operand:SI 1 "register_operand" "0,0,0,r,0") (match_operand:SI 2 "rx_source_operand" "r,Uint04,n,r,Q"))) - (set (reg:CC_ZSC CC_REG) - ;; Note - we do not acknowledge that the SUB instruction sets the Overflow - ;; flag because its interpretation is different from comparing the result - ;; against zero. Compile and run gcc.c-torture/execute/cmpsi-1.c to see this. - (compare:CC_ZSC (minus:SI (match_dup 1) (match_dup 2)) - (const_int 0)))] + (clobber (reg:CC CC_REG))] "" "@ sub\t%2, %0 @@ -1132,32 +1535,134 @@ (set_attr "length" "2,2,6,3,5")] ) -(define_insn "subdi3" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (minus:DI (match_operand:DI 1 "register_operand" "0,0") - (match_operand:DI 2 "rx_source_operand" "r,Q"))) - (set (reg:CC_ZSC CC_REG) ;; See subsi3 - (compare:CC_ZSC (minus:DI (match_dup 1) (match_dup 2)) - (const_int 0)))] - "" - "sub\t%L2, %L0\n\tsbb\t%H2, %H0" - [(set_attr "timings" "22,44") - (set_attr "length" "5,11")] +;; Note that the O flag is set as if (compare op1 op2) not for +;; what is described here, (compare op0 0). +(define_insn "*subsi3_flags" + [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r") + (minus:SI (match_operand:SI 1 "register_operand" "0,0,0,r,0") + (match_operand:SI 2 "rx_source_operand" "r,Uint04,n,r,Q"))) + (set (reg CC_REG) + (compare (minus:SI (match_dup 1) (match_dup 2)) + (const_int 0)))] + "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)" + "@ + sub\t%2, %0 + sub\t%2, %0 + add\t%N2, %0 + sub\t%2, %1, %0 + sub\t%Q2, %0" + [(set_attr "timings" "11,11,11,11,33") + (set_attr "length" "2,2,6,3,5")] ) +;; A helper to expand the above with the CC_MODE filled in. +(define_expand "subsi3_flags" + [(parallel [(set (match_operand:SI 0 "register_operand") + (minus:SI (match_operand:SI 1 "register_operand") + (match_operand:SI 2 "rx_source_operand"))) + (set (reg:CC_ZSC CC_REG) + (compare:CC_ZSC (minus:SI (match_dup 1) (match_dup 2)) + (const_int 0)))])] +) + +(define_insn "sbb_internal" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (minus:SI + (minus:SI + (match_operand:SI 1 "register_operand" " 0,0") + (match_operand:SI 2 "rx_compare_operand" " r,Q")) + (geu:SI (reg:CC CC_REG) (const_int 0)))) + (clobber (reg:CC CC_REG))] + "reload_completed" + "sbb\t%2, %0" + [(set_attr "timings" "11,33") + (set_attr "length" "3,6")] +) + +(define_insn "*sbb_flags" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (minus:SI + (minus:SI + (match_operand:SI 1 "register_operand" " 0,0") + (match_operand:SI 2 "rx_compare_operand" " r,Q")) + (geu:SI (reg:CC CC_REG) (const_int 0)))) + (set (reg CC_REG) + (compare + (minus:SI + (minus:SI (match_dup 1) (match_dup 2)) + (geu:SI (reg:CC CC_REG) (const_int 0))) + (const_int 0)))] + "reload_completed" + "sbb\t%2, %0" + [(set_attr "timings" "11,33") + (set_attr "length" "3,6")] +) + +(define_expand "subdi3" + [(set (match_operand:DI 0 "register_operand" "") + (minus:DI (match_operand:DI 1 "register_operand" "") + (match_operand:DI 2 "rx_source_operand" "")))] + "" +{ + rtx op0l, op0h, op1l, op1h, op2l, op2h; + + op0l = gen_lowpart (SImode, operands[0]); + op1l = gen_lowpart (SImode, operands[1]); + op2l = gen_lowpart (SImode, operands[2]); + op0h = gen_highpart (SImode, operands[0]); + op1h = gen_highpart (SImode, operands[1]); + op2h = gen_highpart_mode (SImode, DImode, operands[2]); + + emit_insn (gen_subdi3_internal (op0l, op0h, op1l, op2l, op1h, op2h)); + DONE; +}) + +(define_insn_and_split "subdi3_internal" + [(set (match_operand:SI 0 "register_operand" "=&r,&r") + (minus:SI (match_operand:SI 2 "register_operand" " 0, r") + (match_operand:SI 3 "rx_source_operand" "rnQ, r"))) + (set (match_operand:SI 1 "register_operand" "= r, r") + (minus:SI + (minus:SI + (match_operand:SI 4 "register_operand" " 1, 1") + (match_operand:SI 5 "rx_compare_operand" " rQ,rQ")) + (geu:SI (match_dup 2) (match_dup 3)))) + (clobber (reg:CC CC_REG))] + "" + "#" + "reload_completed" + [(const_int 0)] +{ + emit_insn (gen_subsi3_flags (operands[0], operands[2], operands[3])); + emit_insn (gen_sbb_internal (operands[1], operands[4], operands[5])); + DONE; +}) + (define_insn "xorsi3" [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r") (xor:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0") (match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q"))) - (set (reg:CC_ZS CC_REG) - (compare:CC_ZS (xor:SI (match_dup 1) (match_dup 2)) - (const_int 0)))] + (clobber (reg:CC CC_REG))] "" "xor\t%Q2, %0" [(set_attr "timings" "11,11,11,11,11,33") (set_attr "length" "3,4,5,6,7,6")] ) + +(define_insn "*xorsi3_flags" + [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r") + (xor:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0") + (match_operand:SI 2 "rx_source_operand" + "r,Sint08,Sint16,Sint24,i,Q"))) + (set (reg CC_REG) + (compare (xor:SI (match_dup 1) (match_dup 2)) + (const_int 0)))] + "reload_completed && rx_match_ccmode (insn, CC_ZSmode)" + "xor\t%Q2, %0" + [(set_attr "timings" "11,11,11,11,11,33") + (set_attr "length" "3,4,5,6,7,6")] +) ;; Floating Point Instructions @@ -1165,9 +1670,7 @@ [(set (match_operand:SF 0 "register_operand" "=r,r,r") (plus:SF (match_operand:SF 1 "register_operand" "%0,0,0") (match_operand:SF 2 "rx_source_operand" "r,F,Q"))) - (set (reg:CC_ZS CC_REG) - (compare:CC_ZS (plus:SF (match_dup 1) (match_dup 2)) - (const_int 0)))] + (clobber (reg:CC CC_REG))] "ALLOW_RX_FPU_INSNS" "fadd\t%2, %0" [(set_attr "timings" "44,44,66") @@ -1178,9 +1681,7 @@ [(set (match_operand:SF 0 "register_operand" "=r,r,r") (div:SF (match_operand:SF 1 "register_operand" "0,0,0") (match_operand:SF 2 "rx_source_operand" "r,F,Q"))) - (set (reg:CC_ZS CC_REG) - (compare:CC_ZS (div:SF (match_dup 1) (match_dup 2)) - (const_int 0)))] + (clobber (reg:CC CC_REG))] "ALLOW_RX_FPU_INSNS" "fdiv\t%2, %0" [(set_attr "timings" "1616,1616,1818") @@ -1191,9 +1692,7 @@ [(set (match_operand:SF 0 "register_operand" "=r,r,r") (mult:SF (match_operand:SF 1 "register_operand" "%0,0,0") (match_operand:SF 2 "rx_source_operand" "r,F,Q"))) - (set (reg:CC_ZS CC_REG) - (compare:CC_ZS (mult:SF (match_dup 1) (match_dup 2)) - (const_int 0)))] + (clobber (reg:CC CC_REG))] "ALLOW_RX_FPU_INSNS" "fmul\t%2, %0" [(set_attr "timings" "33,33,55") @@ -1204,9 +1703,7 @@ [(set (match_operand:SF 0 "register_operand" "=r,r,r") (minus:SF (match_operand:SF 1 "register_operand" "0,0,0") (match_operand:SF 2 "rx_source_operand" "r,F,Q"))) - (set (reg:CC_ZS CC_REG) - (compare:CC_ZS (minus:SF (match_dup 1) (match_dup 2)) - (const_int 0)))] + (clobber (reg:CC CC_REG))] "ALLOW_RX_FPU_INSNS" "fsub\t%Q2, %0" [(set_attr "timings" "44,44,66") @@ -1216,9 +1713,7 @@ (define_insn "fix_truncsfsi2" [(set (match_operand:SI 0 "register_operand" "=r,r") (fix:SI (match_operand:SF 1 "rx_compare_operand" "r,Q"))) - (set (reg:CC_ZS CC_REG) - (compare:CC_ZS (fix:SI (match_dup 1)) - (const_int 0)))] + (clobber (reg:CC CC_REG))] "ALLOW_RX_FPU_INSNS" "ftoi\t%Q1, %0" [(set_attr "timings" "22,44") @@ -1228,9 +1723,7 @@ (define_insn "floatsisf2" [(set (match_operand:SF 0 "register_operand" "=r,r") (float:SF (match_operand:SI 1 "rx_compare_operand" "r,Q"))) - (set (reg:CC_ZS CC_REG) - (compare:CC_ZS (float:SF (match_dup 1)) - (const_int 0)))] + (clobber (reg:CC CC_REG))] "ALLOW_RX_FPU_INSNS" "itof\t%Q1, %0" [(set_attr "timings" "22,44") @@ -1238,217 +1731,216 @@ ) ;; Bit manipulation instructions. -;; Note - there are two versions of each pattern because the memory -;; accessing versions use QImode whilst the register accessing -;; versions use SImode. -;; The peephole are here because the combiner only looks at a maximum -;; of three instructions at a time. - -(define_insn "bitset" - [(set:SI (match_operand:SI 0 "register_operand" "=r") - (ior:SI (match_operand:SI 1 "register_operand" "0") - (ashift:SI (const_int 1) - (match_operand:SI 2 "nonmemory_operand" "ri"))))] - "" - "bset\t%2, %0" + +;; ??? The *_in_memory patterns will not be matched without further help. +;; At one time we had the insv expander generate them, but I suspect that +;; in general we get better performance by exposing the register load to +;; the optimizers. +;; +;; An alternate solution would be to re-organize these patterns such +;; that allow both register and memory operands. This would allow the +;; register allocator to spill and not load the register operand. This +;; would be possible only for operations for which we have a constant +;; bit offset, so that we can adjust the address by ofs/8 and replace +;; the offset in the insn by ofs%8. + +(define_insn "*bitset" + [(set (match_operand:SI 0 "register_operand" "=r") + (ior:SI (ashift:SI (const_int 1) + (match_operand:SI 1 "rx_shift_operand" "ri")) + (match_operand:SI 2 "register_operand" "0")))] + "" + "bset\t%1, %0" [(set_attr "length" "3")] ) -(define_insn "bitset_in_memory" - [(set:QI (match_operand:QI 0 "memory_operand" "=m") - (ior:QI (match_operand:QI 1 "memory_operand" "0") - (ashift:QI (const_int 1) - (match_operand:QI 2 "nonmemory_operand" "ri"))))] +(define_insn "*bitset_in_memory" + [(set (match_operand:QI 0 "memory_operand" "+Q") + (ior:QI (ashift:QI (const_int 1) + (match_operand:QI 1 "nonmemory_operand" "ri")) + (match_dup 0)))] "" - "bset\t%2, %0.B" + "bset\t%1, %0.B" [(set_attr "length" "3") (set_attr "timings" "34")] ) -;; (set (reg A) (const_int 1)) -;; (set (reg A) (ashift (reg A) (reg B))) -;; (set (reg C) (ior (reg A) (reg C))) -(define_peephole2 - [(set:SI (match_operand:SI 0 "register_operand" "") - (const_int 1)) - (set:SI (match_dup 0) - (ashift:SI (match_dup 0) - (match_operand:SI 1 "register_operand" ""))) - (set:SI (match_operand:SI 2 "register_operand" "") - (ior:SI (match_dup 0) - (match_dup 2)))] - "dead_or_set_p (insn, operands[0])" - [(set:SI (match_dup 2) - (ior:SI (match_dup 2) - (ashift:SI (const_int 1) - (match_dup 1))))] -) - -;; (set (reg A) (const_int 1)) -;; (set (reg A) (ashift (reg A) (reg B))) -;; (set (reg A) (ior (reg A) (reg C))) -;; (set (reg C) (reg A) -(define_peephole2 - [(set:SI (match_operand:SI 0 "register_operand" "") - (const_int 1)) - (set:SI (match_dup 0) - (ashift:SI (match_dup 0) - (match_operand:SI 1 "register_operand" ""))) - (set:SI (match_dup 0) - (ior:SI (match_dup 0) - (match_operand:SI 2 "register_operand" ""))) - (set:SI (match_dup 2) (match_dup 0))] - "dead_or_set_p (insn, operands[0])" - [(set:SI (match_dup 2) - (ior:SI (match_dup 2) - (ashift:SI (const_int 1) - (match_dup 1))))] -) - -(define_insn "bitinvert" - [(set:SI (match_operand:SI 0 "register_operand" "+r") - (xor:SI (match_operand:SI 1 "register_operand" "0") - (ashift:SI (const_int 1) - (match_operand:SI 2 "nonmemory_operand" "ri"))))] +(define_insn "*bitinvert" + [(set (match_operand:SI 0 "register_operand" "=r") + (xor:SI (ashift:SI (const_int 1) + (match_operand:SI 1 "rx_shift_operand" "ri")) + (match_operand:SI 2 "register_operand" "0")))] "" - "bnot\t%2, %0" + "bnot\t%1, %0" [(set_attr "length" "3")] ) -(define_insn "bitinvert_in_memory" - [(set:QI (match_operand:QI 0 "memory_operand" "+m") - (xor:QI (match_operand:QI 1 "register_operand" "0") - (ashift:QI (const_int 1) - (match_operand:QI 2 "nonmemory_operand" "ri"))))] +(define_insn "*bitinvert_in_memory" + [(set (match_operand:QI 0 "memory_operand" "+Q") + (xor:QI (ashift:QI (const_int 1) + (match_operand:QI 1 "nonmemory_operand" "ri")) + (match_dup 0)))] "" - "bnot\t%2, %0.B" + "bnot\t%1, %0.B" [(set_attr "length" "5") (set_attr "timings" "33")] ) -;; (set (reg A) (const_int 1)) -;; (set (reg A) (ashift (reg A) (reg B))) -;; (set (reg C) (xor (reg A) (reg C))) -(define_peephole2 - [(set:SI (match_operand:SI 0 "register_operand" "") - (const_int 1)) - (set:SI (match_dup 0) - (ashift:SI (match_dup 0) - (match_operand:SI 1 "register_operand" ""))) - (set:SI (match_operand:SI 2 "register_operand" "") - (xor:SI (match_dup 0) - (match_dup 2)))] - "dead_or_set_p (insn, operands[0])" - [(set:SI (match_dup 2) - (xor:SI (match_dup 2) - (ashift:SI (const_int 1) - (match_dup 1))))] +(define_insn "*bitclr" + [(set (match_operand:SI 0 "register_operand" "=r") + (and:SI (not:SI + (ashift:SI + (const_int 1) + (match_operand:SI 1 "rx_shift_operand" "ri"))) + (match_operand:SI 2 "register_operand" "0")))] "" -) - -;; (set (reg A) (const_int 1)) -;; (set (reg A) (ashift (reg A) (reg B))) -;; (set (reg A) (xor (reg A) (reg C))) -;; (set (reg C) (reg A)) -(define_peephole2 - [(set:SI (match_operand:SI 0 "register_operand" "") - (const_int 1)) - (set:SI (match_dup 0) - (ashift:SI (match_dup 0) - (match_operand:SI 1 "register_operand" ""))) - (set:SI (match_dup 0) - (xor:SI (match_dup 0) - (match_operand:SI 2 "register_operand" ""))) - (set:SI (match_dup 2) (match_dup 0))] - "dead_or_set_p (insn, operands[0])" - [(set:SI (match_dup 2) - (xor:SI (match_dup 2) - (ashift:SI (const_int 1) - (match_dup 1))))] - "" -) - -(define_insn "bitclr" - [(set:SI (match_operand:SI 0 "register_operand" "=r") - (and:SI (match_operand:SI 1 "register_operand" "0") - (not:SI (ashift:SI (const_int 1) - (match_operand:SI 2 "nonmemory_operand" "ri")))))] - "" - "bclr\t%2, %0" + "bclr\t%1, %0" [(set_attr "length" "3")] ) -(define_insn "bitclr_in_memory" - [(set:QI (match_operand:QI 0 "memory_operand" "=m") - (and:QI (match_operand:QI 1 "memory_operand" "0") - (not:QI (ashift:QI (const_int 1) - (match_operand:QI 2 "nonmemory_operand" "ri")))))] +(define_insn "*bitclr_in_memory" + [(set (match_operand:QI 0 "memory_operand" "+Q") + (and:QI (not:QI + (ashift:QI + (const_int 1) + (match_operand:QI 1 "nonmemory_operand" "ri"))) + (match_dup 0)))] "" - "bclr\t%2, %0.B" + "bclr\t%1, %0.B" [(set_attr "length" "3") (set_attr "timings" "34")] ) -;; (set (reg A) (const_int -2)) -;; (set (reg A) (rotate (reg A) (reg B))) -;; (set (reg C) (and (reg A) (reg C))) -(define_peephole2 - [(set:SI (match_operand:SI 0 "register_operand" "") - (const_int -2)) - (set:SI (match_dup 0) - (rotate:SI (match_dup 0) - (match_operand:SI 1 "register_operand" ""))) - (set:SI (match_operand:SI 2 "register_operand" "") - (and:SI (match_dup 0) - (match_dup 2)))] - "dead_or_set_p (insn, operands[0])" - [(set:SI (match_dup 2) - (and:SI (match_dup 2) - (not:SI (ashift:SI (const_int 1) - (match_dup 1)))))] +(define_insn "*insv_imm" + [(set (zero_extract:SI + (match_operand:SI 0 "register_operand" "+r") + (const_int 1) + (match_operand:SI 1 "rx_shift_operand" "ri")) + (match_operand:SI 2 "const_int_operand" ""))] + "" +{ + if (INTVAL (operands[2]) & 1) + return "bset\t%1, %0"; + else + return "bclr\t%1, %0"; +} + [(set_attr "length" "3")] ) - -;; (set (reg A) (const_int -2)) -;; (set (reg A) (rotate (reg A) (reg B))) -;; (set (reg A) (and (reg A) (reg C))) -;; (set (reg C) (reg A) -(define_peephole2 - [(set:SI (match_operand:SI 0 "register_operand" "") - (const_int -2)) - (set:SI (match_dup 0) - (rotate:SI (match_dup 0) - (match_operand:SI 1 "register_operand" ""))) - (set:SI (match_dup 0) - (and:SI (match_dup 0) - (match_operand:SI 2 "register_operand" ""))) - (set:SI (match_dup 2) (match_dup 0))] - "dead_or_set_p (insn, operands[0])" - [(set:SI (match_dup 2) - (and:SI (match_dup 2) - (not:SI (ashift:SI (const_int 1) - (match_dup 1)))))] + +(define_insn_and_split "rx_insv_reg" + [(set (zero_extract:SI + (match_operand:SI 0 "register_operand" "+r") + (const_int 1) + (match_operand:SI 1 "const_int_operand" "")) + (match_operand:SI 2 "register_operand" "r")) + (clobber (reg:CC CC_REG))] + "" + "#" + "reload_completed" + [(set (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1)) + (match_dup 3))] +{ + rtx flags, x; + + /* Emit tst #1, op2. */ + flags = gen_rtx_REG (CC_ZSmode, CC_REG); + x = gen_rtx_AND (SImode, operands[2], const1_rtx); + x = gen_rtx_COMPARE (CC_ZSmode, x, const0_rtx); + x = gen_rtx_SET (VOIDmode, flags, x); + emit_insn (x); + + /* Emit bmne. */ + operands[3] = gen_rtx_NE (SImode, flags, const0_rtx); +}) + +(define_insn_and_split "*insv_cond" + [(set (zero_extract:SI + (match_operand:SI 0 "register_operand" "+r") + (const_int 1) + (match_operand:SI 1 "const_int_operand" "")) + (match_operator:SI 4 "comparison_operator" + [(match_operand:SI 2 "register_operand" "r") + (match_operand:SI 3 "rx_source_operand" "riQ")])) + (clobber (reg:CC CC_REG))] + "" + "#" + "reload_completed" + [(set (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1)) + (match_dup 4))] +{ + rtx flags, x; + + flags = gen_rtx_REG (CCmode, CC_REG); + x = gen_rtx_COMPARE (CCmode, operands[2], operands[3]); + x = gen_rtx_SET (VOIDmode, flags, x); + emit_insn (x); + + operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[4]), SImode, + flags, const0_rtx); +}) + +(define_insn "*bmcc" + [(set (zero_extract:SI + (match_operand:SI 0 "register_operand" "+r") + (const_int 1) + (match_operand:SI 1 "const_int_operand" "")) + (match_operator:SI 2 "comparison_operator" + [(reg CC_REG) (const_int 0)]))] + "reload_completed" + "bm%B2\t%1, %0" + [(set_attr "length" "3")] ) -(define_expand "insv" - [(set:SI (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand") ;; Destination - (match_operand 1 "immediate_operand") ;; # of bits to set - (match_operand 2 "immediate_operand")) ;; Starting bit - (match_operand 3 "immediate_operand"))] ;; Bits to insert +;; Work around the fact that X=Y<0 is preferentially expanded as a shift. +(define_insn_and_split "*insv_cond_lt" + [(set (zero_extract:SI + (match_operand:SI 0 "register_operand" "+r") + (const_int 1) + (match_operand:SI 1 "const_int_operand" "")) + (match_operator:SI 3 "rshift_operator" + [(match_operand:SI 2 "register_operand" "r") + (const_int 31)])) + (clobber (reg:CC CC_REG))] "" - { - if (rx_expand_insv (operands)) + "#" + "" + [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1)) + (lt:SI (match_dup 2) (const_int 0))) + (clobber (reg:CC CC_REG))])] + "" +) + +(define_expand "insv" + [(set (zero_extract:SI + (match_operand:SI 0 "register_operand") ;; Destination + (match_operand:SI 1 "const_int_operand") ;; # of bits to set + (match_operand:SI 2 "nonmemory_operand")) ;; Starting bit + (match_operand:SI 3 "nonmemory_operand"))] ;; Bits to insert + "" +{ + /* We only handle single-bit inserts. */ + if (!CONST_INT_P (operands[1]) || INTVAL (operands[1]) != 1) + FAIL; + + /* Either the bit to insert or the position must be constant. */ + if (CONST_INT_P (operands[3])) + operands[3] = GEN_INT (INTVAL (operands[3]) & 1); + else if (CONST_INT_P (operands[2])) + { + emit_insn (gen_rx_insv_reg (operands[0], operands[2], operands[3])); DONE; + } + else FAIL; - } -) +}) ;; Atomic exchange operation. (define_insn "sync_lock_test_and_setsi" - [(set:SI (match_operand:SI 0 "register_operand" "=r,r") - (match_operand:SI 1 "rx_compare_operand" "=r,Q")) - (set:SI (match_dup 1) - (match_operand:SI 2 "register_operand" "0,0"))] + [(set (match_operand:SI 0 "register_operand" "=r,r") + (match_operand:SI 1 "rx_compare_operand" "=r,Q")) + (set (match_dup 1) + (match_operand:SI 2 "register_operand" "0,0"))] "" "xchg\t%1, %0" [(set_attr "length" "3,6") @@ -1458,9 +1950,9 @@ ;; Block move functions. (define_expand "movstr" - [(set:SI (match_operand:BLK 1 "memory_operand") ;; Dest - (match_operand:BLK 2 "memory_operand")) ;; Source - (use (match_operand:SI 0 "register_operand")) ;; Updated Dest + [(set (match_operand:BLK 1 "memory_operand") ;; Dest + (match_operand:BLK 2 "memory_operand")) ;; Source + (use (match_operand:SI 0 "register_operand")) ;; Updated Dest ] "" { @@ -1483,8 +1975,8 @@ ) (define_insn "rx_movstr" - [(set:SI (mem:BLK (reg:SI 1)) - (mem:BLK (reg:SI 2))) + [(set (mem:BLK (reg:SI 1)) + (mem:BLK (reg:SI 2))) (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_MOVSTR) (clobber (reg:SI 1)) (clobber (reg:SI 2)) @@ -1496,8 +1988,8 @@ ) (define_insn "rx_strend" - [(set:SI (match_operand:SI 0 "register_operand" "=r") - (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "r") + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "r") (reg:SI 3)] UNSPEC_STRLEN)) (clobber (reg:SI 1)) (clobber (reg:SI 2)) @@ -1578,8 +2070,8 @@ ) (define_insn "rx_setmem" - [(set:BLK (mem:BLK (reg:SI 1)) (reg 2)) - (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_SETMEM) + [(set (mem:BLK (reg:SI 1)) + (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_SETMEM)) (clobber (reg:SI 1)) (clobber (reg:SI 3))] "" @@ -1632,11 +2124,11 @@ ) (define_insn "rx_cmpstrn" - [(set:SI (match_operand:SI 0 "register_operand" "=r") - (unspec_volatile:SI [(reg:SI 1) (reg:SI 2) (reg:SI 3)] - UNSPEC_CMPSTRN)) - (use (match_operand:BLK 1 "memory_operand" "m")) - (use (match_operand:BLK 2 "memory_operand" "m")) + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec_volatile:SI [(reg:SI 1) (reg:SI 2) (reg:SI 3)] + UNSPEC_CMPSTRN)) + (use (match_operand:BLK 1 "memory_operand" "m")) + (use (match_operand:BLK 2 "memory_operand" "m")) (clobber (reg:SI 1)) (clobber (reg:SI 2)) (clobber (reg:SI 3)) @@ -1769,7 +2261,7 @@ ;; Byte swap (two 16-bit values). (define_insn "revw" - [(set (match_operand:SI 0 "register_operand" "+r") + [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(match_operand:SI 1 "register_operand" "r")] UNSPEC_BUILTIN_REVW))] "" @@ -1789,16 +2281,6 @@ (set_attr "length" "3,5")] ) -;; Saturate to 32-bits -(define_insn "sat" - [(set (match_operand:SI 0 "register_operand" "=r") - (unspec:SI [(match_operand:SI 1 "register_operand" "0")] - UNSPEC_BUILTIN_SAT))] - "" - "sat\t%0" - [(set_attr "length" "2")] -) - ;;---------- Control Registers ------------------------ ;; Clear Processor Status Word diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index 62fc32830af..109aa1b27c3 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -300,12 +300,6 @@ static HOST_WIDE_INT actual_fsize; saved (as 4-byte quantities). */ static int num_gfregs; -/* The alias set for prologue/epilogue register save/restore. */ -static GTY(()) alias_set_type sparc_sr_alias_set; - -/* The alias set for the structure return value. */ -static GTY(()) alias_set_type struct_value_alias_set; - /* Vector to say how input registers are mapped to output registers. HARD_FRAME_POINTER_REGNUM cannot be remapped by this function to eliminate it. You must use -fomit-frame-pointer to get that. */ @@ -912,10 +906,6 @@ sparc_option_override (void) /* Do various machine dependent initializations. */ sparc_init_modes (); - /* Acquire unique alias sets for our private stuff. */ - sparc_sr_alias_set = new_alias_set (); - struct_value_alias_set = new_alias_set (); - /* Set up function hooks. */ init_machine_status = sparc_init_machine_status; @@ -4381,8 +4371,7 @@ save_or_restore_regs (int low, int high, rtx base, int offset, int action) { if (df_regs_ever_live_p (i) && ! call_used_regs[i]) { - mem = gen_rtx_MEM (DImode, plus_constant (base, offset)); - set_mem_alias_set (mem, sparc_sr_alias_set); + mem = gen_frame_mem (DImode, plus_constant (base, offset)); if (action == SORR_SAVE) { insn = emit_move_insn (mem, gen_rtx_REG (DImode, i)); @@ -4422,8 +4411,7 @@ save_or_restore_regs (int low, int high, rtx base, int offset, int action) else continue; - mem = gen_rtx_MEM (mode, plus_constant (base, offset)); - set_mem_alias_set (mem, sparc_sr_alias_set); + mem = gen_frame_mem (mode, plus_constant (base, offset)); if (action == SORR_SAVE) { insn = emit_move_insn (mem, gen_rtx_REG (mode, regno)); @@ -6087,11 +6075,11 @@ sparc_struct_value_rtx (tree fndecl, int incoming) rtx mem; if (incoming) - mem = gen_rtx_MEM (Pmode, plus_constant (frame_pointer_rtx, - STRUCT_VALUE_OFFSET)); + mem = gen_frame_mem (Pmode, plus_constant (frame_pointer_rtx, + STRUCT_VALUE_OFFSET)); else - mem = gen_rtx_MEM (Pmode, plus_constant (stack_pointer_rtx, - STRUCT_VALUE_OFFSET)); + mem = gen_frame_mem (Pmode, plus_constant (stack_pointer_rtx, + STRUCT_VALUE_OFFSET)); /* Only follow the SPARC ABI for fixed-size structure returns. Variable size structure returns are handled per the normal @@ -6133,7 +6121,6 @@ sparc_struct_value_rtx (tree fndecl, int incoming) emit_label (endlab); } - set_mem_alias_set (mem, struct_value_alias_set); return mem; } } diff --git a/gcc/config/spu/spu.c b/gcc/config/spu/spu.c index e141a154691..324ac4df21c 100644 --- a/gcc/config/spu/spu.c +++ b/gcc/config/spu/spu.c @@ -230,6 +230,7 @@ static void spu_unique_section (tree, int); static rtx spu_expand_load (rtx, rtx, rtx, int); static void spu_trampoline_init (rtx, tree, rtx); static void spu_conditional_register_usage (void); +static bool spu_ref_may_alias_errno (ao_ref *); /* Which instruction set architecture to use. */ int spu_arch; @@ -491,6 +492,9 @@ static const struct attribute_spec spu_attribute_table[] = #undef TARGET_CONDITIONAL_REGISTER_USAGE #define TARGET_CONDITIONAL_REGISTER_USAGE spu_conditional_register_usage +#undef TARGET_REF_MAY_ALIAS_ERRNO +#define TARGET_REF_MAY_ALIAS_ERRNO spu_ref_may_alias_errno + struct gcc_target targetm = TARGET_INITIALIZER; static void @@ -7150,4 +7154,28 @@ spu_function_profiler (FILE * file, int labelno ATTRIBUTE_UNUSED) fprintf (file, "brsl $75, _mcount\n"); } +/* Implement targetm.ref_may_alias_errno. */ +static bool +spu_ref_may_alias_errno (ao_ref *ref) +{ + tree base = ao_ref_base (ref); + + /* With SPU newlib, errno is defined as something like + _impure_data._errno + The default implementation of this target macro does not + recognize such expressions, so special-code for it here. */ + + if (TREE_CODE (base) == VAR_DECL + && !TREE_STATIC (base) + && DECL_EXTERNAL (base) + && TREE_CODE (TREE_TYPE (base)) == RECORD_TYPE + && strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (base)), + "_impure_data") == 0 + /* _errno is the first member of _impure_data. */ + && ref->offset == 0) + return true; + + return default_ref_may_alias_errno (ref); +} + #include "gt-spu.h" diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e7b45b4830b..249104773f6 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,16 @@ +2011-01-17 Jason Merrill <jason@redhat.com> + + PR c++/47067 + * semantics.c (base_field_constructor_elt): New fn. + (cxx_eval_bare_aggregate): Use it. + (build_data_member_initialization): Leave COMPONENT_REF for + vfield inits. + +2011-01-14 Rodrigo Rivas Costa <rodrigorivascosta@gmail.com> + + * parser.c (cp_parser_range_for): Remove the "unused variable" warning + workaround. + 2011-01-15 Giovanni Funchal <gafunchal@gmail.com> Jonathan Wakely <jwakely.gcc@gmail.com> diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 061e8cc7fee..41f82ac4747 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -8760,15 +8760,6 @@ cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl) { tree stmt, range_expr; - /* If the variable from a range-for is not actually used, GCC would issue - "unused variable" warnings, and the user could do little to prevent them. - So we always mark it as used. */ - if (range_decl != error_mark_node) - { - TREE_USED (range_decl) = 1; - DECL_READ_P (range_decl) = 1; - } - if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) { bool expr_non_constant_p; diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index b9775f4b909..285b764e2c7 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -5538,7 +5538,11 @@ build_data_member_initialization (tree t, VEC(constructor_elt,gc) **vec) } if (TREE_CODE (member) == ADDR_EXPR) member = TREE_OPERAND (member, 0); - if (TREE_CODE (member) == COMPONENT_REF) + if (TREE_CODE (member) == COMPONENT_REF + /* If we're initializing a member of a subaggregate, it's a vtable + pointer. Leave it as COMPONENT_REF so we remember the path to get + to the vfield. */ + && TREE_CODE (TREE_OPERAND (member, 0)) != COMPONENT_REF) member = TREE_OPERAND (member, 1); CONSTRUCTOR_APPEND_ELT (*vec, member, init); return true; @@ -6350,6 +6354,36 @@ cxx_eval_logical_expression (const constexpr_call *call, tree t, return r; } +/* REF is a COMPONENT_REF designating a particular field. V is a vector of + CONSTRUCTOR elements to initialize (part of) an object containing that + field. Return a pointer to the constructor_elt corresponding to the + initialization of the field. */ + +static constructor_elt * +base_field_constructor_elt (VEC(constructor_elt,gc) *v, tree ref) +{ + tree aggr = TREE_OPERAND (ref, 0); + tree field = TREE_OPERAND (ref, 1); + HOST_WIDE_INT i; + constructor_elt *ce; + + gcc_assert (TREE_CODE (ref) == COMPONENT_REF); + + if (TREE_CODE (aggr) == COMPONENT_REF) + { + constructor_elt *base_ce + = base_field_constructor_elt (v, aggr); + v = CONSTRUCTOR_ELTS (base_ce->value); + } + + for (i = 0; VEC_iterate (constructor_elt, v, i, ce); ++i) + if (ce->index == field) + return ce; + + gcc_unreachable (); + return NULL; +} + /* Subroutine of cxx_eval_constant_expression. The expression tree T denotes a C-style array or a C-style aggregate. Reduce it to a constant expression. */ @@ -6365,7 +6399,6 @@ cxx_eval_bare_aggregate (const constexpr_call *call, tree t, constructor_elt *ce; HOST_WIDE_INT i; bool changed = false; - tree type = TREE_TYPE (t); gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (t)); for (i = 0; VEC_iterate (constructor_elt, v, i, ce); ++i) { @@ -6377,23 +6410,13 @@ cxx_eval_bare_aggregate (const constexpr_call *call, tree t, goto fail; if (elt != ce->value) changed = true; - if (TREE_CODE (type) != ARRAY_TYPE - && !(same_type_ignoring_top_level_qualifiers_p - (DECL_CONTEXT (ce->index), type))) + if (TREE_CODE (ce->index) == COMPONENT_REF) { - /* Push our vtable pointer down into the base where it belongs. */ - tree vptr_base = DECL_CONTEXT (ce->index); - tree base_ctor; - gcc_assert (ce->index == TYPE_VFIELD (type)); - for (base_ctor = VEC_index (constructor_elt, n, 0)->value; ; - base_ctor = CONSTRUCTOR_ELT (base_ctor, 0)->value) - if (TREE_TYPE (base_ctor) == vptr_base) - { - constructor_elt *p = CONSTRUCTOR_ELT (base_ctor, 0); - gcc_assert (p->index == ce->index); - p->value = elt; - break; - } + /* This is an initialization of a vfield inside a base + subaggregate that we already initialized; push this + initialization into the previous initialization. */ + constructor_elt *inner = base_field_constructor_elt (n, ce->index); + inner->value = elt; } else CONSTRUCTOR_APPEND_ELT (n, ce->index, elt); diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 958541b1ee4..ab65fd6848e 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -934,6 +934,7 @@ typedef _Complex float __attribute__((mode(XC))) _Complex80; Not all targets support additional floating point types. @code{__float80} and @code{__float128} types are supported on i386, x86_64 and ia64 targets. +The @code{__float128} type is supported on hppa HP-UX targets. @node Half-Precision @section Half-Precision Floating Point diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi index bc9b013cccd..3546170e491 100644 --- a/gcc/doc/install.texi +++ b/gcc/doc/install.texi @@ -1046,7 +1046,8 @@ endians, with little endian being the default: Example 2: to configure a compiler for both SH4A and SH4AL-DSP, but with only little endian SH4AL: @smallexample ---with-cpu=sh4a --with-endian=little,big --with-multilib-list=sh4al,!mb/m4al +--with-cpu=sh4a --with-endian=little,big \ +--with-multilib-list=sh4al,!mb/m4al @end smallexample @item --with-endian=@var{endians} @@ -1559,17 +1560,17 @@ If you do not have GMP (the GNU Multiple Precision library), the MPFR library and/or the MPC library installed in a standard location and you want to build GCC, you can explicitly specify the directory where they are installed (@samp{--with-gmp=@var{gmpinstalldir}}, -@samp{--with-mpfr=@var{mpfrinstalldir}}, -@samp{--with-mpc=@var{mpcinstalldir}}). The -@option{--with-gmp=@var{gmpinstalldir}} option is shorthand for -@option{--with-gmp-lib=@var{gmpinstalldir}/lib} and -@option{--with-gmp-include=@var{gmpinstalldir}/include}. Likewise the -@option{--with-mpfr=@var{mpfrinstalldir}} option is shorthand for -@option{--with-mpfr-lib=@var{mpfrinstalldir}/lib} and -@option{--with-mpfr-include=@var{mpfrinstalldir}/include}, also the -@option{--with-mpc=@var{mpcinstalldir}} option is shorthand for -@option{--with-mpc-lib=@var{mpcinstalldir}/lib} and -@option{--with-mpc-include=@var{mpcinstalldir}/include}. If these +@samp{--with-mpfr=@/@var{mpfrinstalldir}}, +@samp{--with-mpc=@/@var{mpcinstalldir}}). The +@option{--with-gmp=@/@var{gmpinstalldir}} option is shorthand for +@option{--with-gmp-lib=@/@var{gmpinstalldir}/lib} and +@option{--with-gmp-include=@/@var{gmpinstalldir}/include}. Likewise the +@option{--with-mpfr=@/@var{mpfrinstalldir}} option is shorthand for +@option{--with-mpfr-lib=@/@var{mpfrinstalldir}/lib} and +@option{--with-mpfr-include=@/@var{mpfrinstalldir}/include}, also the +@option{--with-mpc=@/@var{mpcinstalldir}} option is shorthand for +@option{--with-mpc-lib=@/@var{mpcinstalldir}/lib} and +@option{--with-mpc-include=@/@var{mpcinstalldir}/include}. If these shorthand assumptions are not correct, you can use the explicit include and lib options directly. You might also need to ensure the shared libraries can be found by the dynamic linker when building and @@ -1585,14 +1586,14 @@ variable (@env{LD_LIBRARY_PATH} on GNU/Linux and Solaris systems). If you do not have PPL (the Parma Polyhedra Library) and the CLooG libraries installed in a standard location and you want to build GCC, you can explicitly specify the directory where they are installed -(@samp{--with-ppl=@var{pplinstalldir}}, -@samp{--with-cloog=@var{clooginstalldir}}). The -@option{--with-ppl=@var{pplinstalldir}} option is shorthand for -@option{--with-ppl-lib=@var{pplinstalldir}/lib} and -@option{--with-ppl-include=@var{pplinstalldir}/include}. Likewise the -@option{--with-cloog=@var{clooginstalldir}} option is shorthand for -@option{--with-cloog-lib=@var{clooginstalldir}/lib} and -@option{--with-cloog-include=@var{clooginstalldir}/include}. If these +(@samp{--with-ppl=@/@var{pplinstalldir}}, +@samp{--with-cloog=@/@var{clooginstalldir}}). The +@option{--with-ppl=@/@var{pplinstalldir}} option is shorthand for +@option{--with-ppl-lib=@/@var{pplinstalldir}/lib} and +@option{--with-ppl-include=@/@var{pplinstalldir}/include}. Likewise the +@option{--with-cloog=@/@var{clooginstalldir}} option is shorthand for +@option{--with-cloog-lib=@/@var{clooginstalldir}/lib} and +@option{--with-cloog-include=@/@var{clooginstalldir}/include}. If these shorthand assumptions are not correct, you can use the explicit include and lib options directly. @@ -3223,7 +3224,7 @@ For @code{cris-axis-elf} you need binutils 2.11 or newer. For @code{cris-axis-linux-gnu} you need binutils 2.12 or newer. Pre-packaged tools can be obtained from -@uref{ftp://ftp.axis.com/pub/axis/tools/cris/compiler-kit/}. More +@uref{ftp://ftp.axis.com/@/pub/@/axis/@/tools/@/cris/@/compiler-kit/}. More information about this platform is available at @uref{http://developer.axis.com/}. @@ -3250,8 +3251,11 @@ is also used to build the @samp{newlib} C library for CRX. It is also possible to build libstdc++-v3 for the CRX architecture. This needs to be done in a separate step with the following configure settings: -@samp{gcc/libstdc++-v3/configure --host=crx-elf --with-newlib ---enable-sjlj-exceptions --enable-cxx-flags='-fexceptions -frtti'} + +@smallexample +gcc/libstdc++-v3/configure --host=crx-elf --with-newlib \ + --enable-sjlj-exceptions --enable-cxx-flags='-fexceptions -frtti' +@end smallexample @html <hr /> @@ -3573,8 +3577,8 @@ due to a packaging bug the version in Solaris 10, from GNU binutils 2.19, works, as does the latest version, from GNU binutils 2.20.1. To use GNU @command{as}, configure with the options -@option{--with-gnu-as --with-as=/usr/sfw/bin/gas}. It may be necessary -to configure with @option{--without-gnu-ld --with-ld=/usr/ccs/bin/ld} to +@option{--with-gnu-as --with-as=@//usr/@/sfw/@/bin/@/gas}. It may be necessary +to configure with @option{--without-gnu-ld --with-ld=@//usr/@/ccs/@/bin/@/ld} to guarantee use of Sun @command{ld}. @c FIXME: why --without-gnu-ld --with-ld? diff --git a/gcc/doc/lto.texi b/gcc/doc/lto.texi index 8daa8310aea..069dafb76e3 100644 --- a/gcc/doc/lto.texi +++ b/gcc/doc/lto.texi @@ -27,7 +27,7 @@ the files. Additionally, one might be able to ship one set of fat objects which could be used both for development and the production of optimized builds. A, perhaps surprising, side effect of this feature is that any mistake in the toolchain that leads to LTO information not -being used (e.g. an older @code{libtool} calling @code{ld} directly). +being used (e.g.@: an older @code{libtool} calling @code{ld} directly). This is both an advantage, as the system is more robust, and a disadvantage, as the user is not informed that the optimization has been disabled. @@ -54,7 +54,7 @@ Currently, this phase is composed of two IPA passes: @item @code{pass_ipa_lto_gimple_out} This pass executes the function @code{lto_output} in @file{lto-streamer-out.c}, which traverses the call graph encoding -every reachable declaration, type and function. This generates a +every reachable declaration, type and function. This generates a memory representation of all the file sections described below. @item @code{pass_ipa_lto_finish_out} @@ -98,33 +98,33 @@ would be easy to implement. WHOPR splits LTO into three main stages: @enumerate @item Local generation (LGEN) -This stage executes in parallel. Every file in the program is compiled +This stage executes in parallel. Every file in the program is compiled into the intermediate language and packaged together with the local call-graph and summary information. This stage is the same for both the LTO and WHOPR compilation mode. @item Whole Program Analysis (WPA) -WPA is performed sequentially. The global call-graph is generated, and -a global analysis procedure makes transformation decisions. The global +WPA is performed sequentially. The global call-graph is generated, and +a global analysis procedure makes transformation decisions. The global call-graph is partitioned to facilitate parallel optimization during -phase 3. The results of the WPA stage are stored into new object files +phase 3. The results of the WPA stage are stored into new object files which contain the partitions of program expressed in the intermediate language and the optimization decisions. @item Local transformations (LTRANS) -This stage executes in parallel. All the decisions made during phase 2 +This stage executes in parallel. All the decisions made during phase 2 are implemented locally in each partitioned object file, and the final -object code is generated. Optimizations which cannot be decided +object code is generated. Optimizations which cannot be decided efficiently during the phase 2 may be performed on the local call-graph partitions. @end enumerate WHOPR can be seen as an extension of the usual LTO mode of -compilation. In LTO, WPA and LTRANS and are executed within a single +compilation. In LTO, WPA and LTRANS are executed within a single execution of the compiler, after the whole program has been read into memory. -When compiling in WHOPR mode the callgraph is partitioned during +When compiling in WHOPR mode, the callgraph is partitioned during the WPA stage. The whole program is split into a given number of partitions of roughly the same size. The compiler tries to minimize the number of references which cross partition boundaries. @@ -149,13 +149,13 @@ are described below. @item Command line options (@code{.gnu.lto_.opts}) This section contains the command line options used to generate the -object files. This is used at link-time to determine the optimization +object files. This is used at link time to determine the optimization level and other settings when they are not explicitly specified at the linker command line. Currently, GCC does not support combining LTO object files compiled with different set of the command line options into a single binary. -At link-time, the options given on the command line and the options +At link time, the options given on the command line and the options saved on all the files in a link-time set are applied globally. No attempt is made at validating the combination of flags (other than the usual validation done by option processing). This is implemented in @@ -165,7 +165,7 @@ usual validation done by option processing). This is implemented in @item Symbol table (@code{.gnu.lto_.symtab}) This table replaces the ELF symbol table for functions and variables -represented in the LTO IL. Symbols used and exported by the optimized +represented in the LTO IL. Symbols used and exported by the optimized assembly code of ``fat'' objects might not match the ones used and exported by the intermediate code. This table is necessary because the intermediate code is less optimized and thus requires a separate @@ -174,7 +174,7 @@ symbol table. Additionally, the binary code in the ``fat'' object will lack a call to a function, since the call was optimized out at compilation time after the intermediate language was streamed out. In some special -cases, the same optimization may not happen during link-time +cases, the same optimization may not happen during link-time optimization. This would lead to an undefined symbol if only one symbol table was used. @@ -198,7 +198,7 @@ of pointers when the file is read back in @item The callgraph (@code{.gnu.lto_.cgraph}) This section contains the basic data structure used by the GCC -inter-procedural optimization infrastructure. This section stores an +inter-procedural optimization infrastructure. This section stores an annotated multi-graph which represents the functions and call sites as well as the variables, aliases and top-level @code{asm} statements. @@ -217,7 +217,7 @@ and read by @file{lto-cgraph.c}:@code{input_refs}. @item Function bodies (@code{.gnu.lto_.function_body.<name>}) This section contains function bodies in the intermediate language -representation. Every function body is in a separate section to allow +representation. Every function body is in a separate section to allow copying of the section independently to different object files or reading the function on demand. @@ -263,12 +263,12 @@ that are executed at different times during WHOPR compilation: @item LGEN time @enumerate @item @emph{Generate summary} (@code{generate_summary} in -@code{struct ipa_opt_pass_d}). This stage analyzes every function +@code{struct ipa_opt_pass_d}). This stage analyzes every function body and variable initializer is examined and stores relevant information into a pass-specific data structure. @item @emph{Write summary} (@code{write_summary} in -@code{struct ipa_opt_pass_d}. This stage writes all the +@code{struct ipa_opt_pass_d}. This stage writes all the pass-specific information generated by @code{generate_summary}. Summaries go into their own @code{LTO_section_*} sections that have to be declared in @file{lto-streamer.h}:@code{enum @@ -280,7 +280,7 @@ lto_section_type}. A new section is created by calling @item WPA time @enumerate @item @emph{Read summary} (@code{read_summary} in -@code{struct ipa_opt_pass_d}). This stage reads all the +@code{struct ipa_opt_pass_d}). This stage reads all the pass-specific information in exactly the same order that it was written by @code{write_summary}. @@ -335,7 +335,7 @@ between normal inter-procedural passes and small inter-procedural passes. A @emph{small inter-procedural pass} (@code{SIMPLE_IPA_PASS}) is a pass that does everything at once and thus it can not be executed during WPA in -WHOPR mode. It defines only the @emph{Execute} stage and during +WHOPR mode. It defines only the @emph{Execute} stage and during this stage it accesses and modifies the function bodies. Such passes are useful for optimization at LGEN or LTRANS time and are used, for example, to implement early optimization before writing @@ -367,7 +367,7 @@ Most optimization passes split naturally into analysis, propagation and transformation stages. But some do not. The main problem arises when one pass performs changes and the following pass gets confused by seeing different callgraphs -betwee the @emph{Transform} stage and the @emph{Generate summary} +between the @emph{Transform} stage and the @emph{Generate summary} or @emph{Execute} stage. This means that the passes are required to communicate their decisions with each other. @@ -430,7 +430,7 @@ GCC represents IPA references in the callgraph. For a function or variable @code{A}, the @emph{IPA reference} is a list of all locations where the address of @code{A} is taken and, when @code{A} is a variable, a list of all direct stores and reads -to/from @code{A}. References represent an oriented multi-graph on +to/from @code{A}. References represent an oriented multi-graph on the union of nodes of the callgraph and the varpool. See @file{ipa-reference.c}:@code{ipa_reference_write_optimization_summary} and @@ -454,7 +454,7 @@ Link-time optimization gives relatively minor benefits when used alone. The problem is that propagation of inter-procedural information does not work well across functions and variables that are called or referenced by other compilation units (such as -from a dynamically linked library). We say that such functions +from a dynamically linked library). We say that such functions are variables are @emph{externally visible}. To make the situation even more difficult, many applications @@ -476,7 +476,7 @@ provided with the link-time information. In GCC, the whole program option (@option{-fwhole-program}) asserts that every function and variable defined in the current compilation unit is static, except for function @code{main} (note: at -link-time, the current unit is the union of all objects compiled +link time, the current unit is the union of all objects compiled with LTO). Since some functions and variables need to be referenced externally, for example by another DSO or from an assembler file, GCC also provides the function and variable @@ -485,7 +485,7 @@ the effect of @option{-fwhole-program} on a specific symbol. The whole program mode assumptions are slightly more complex in C++, where inline functions in headers are put into @emph{COMDAT} -sections. COMDAT function and variables can be defined by +sections. COMDAT function and variables can be defined by multiple object files and their bodies are unified at link-time and dynamic link-time. COMDAT functions are changed to local only when their address is not taken and thus un-sharing them with a @@ -500,9 +500,9 @@ externally visible symbols (or alternatively an the @code{default}, @code{protected}, @code{hidden} and @code{internal} visibilities. -The most commonly used is visibility is @code{hidden}. It +The most commonly used is visibility is @code{hidden}. It specifies that the symbol cannot be referenced from outside of -the current shared library. Unfortunately, this information +the current shared library. Unfortunately, this information cannot be used directly by the link-time optimization in the compiler since the whole shared library also might contain non-LTO objects and those are not visible to the compiler. @@ -519,7 +519,7 @@ which symbols provided by the claimed objects are bound from the rest of a binary being linked. Currently, the linker plugin works only in combination -with the Gold linker, but a GNU ld implementation is under +with the Gold linker, but a GNU ld implementation is under development. GCC is designed to be independent of the rest of the toolchain @@ -528,7 +528,7 @@ reason it does not use the linker plugin by default. Instead, the object files are examined by @command{collect2} before being passed to the linker and objects found to have LTO sections are passed to @command{lto1} first. This mode does not work for -library archives. The decision on what object files from the +library archives. The decision on what object files from the archive are needed depends on the actual linking and thus GCC would have to implement the linker itself. The resolution information is missing too and thus GCC needs to make an educated @@ -557,7 +557,7 @@ bodies. It then drives the LTRANS phase. @opindex fltrans This option runs the link-time optimizer in the local-transformation (LTRANS) mode, which reads in output from a -previous run of the LTO in WPA mode. In the LTRANS mode, LTO +previous run of the LTO in WPA mode. In the LTRANS mode, LTO optimizes an object and produces the final assembly. @item -fltrans-output-list=@var{file} diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index 0839d0bff78..4ff5d4edc8a 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -59,6 +59,7 @@ along with GCC; see the file COPYING3. If not see #include "df.h" #include "params.h" #include "target.h" +#include "tree-flow.h" struct target_rtl default_target_rtl; #if SWITCHABLE_TARGET @@ -1669,33 +1670,10 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp, || TREE_CODE (t) == SAVE_EXPR) t = TREE_OPERAND (t, 0); - /* We may look through structure-like accesses for the purposes of - examining TREE_THIS_NOTRAP, but not array-like accesses. */ - base = t; - while (TREE_CODE (base) == COMPONENT_REF - || TREE_CODE (base) == REALPART_EXPR - || TREE_CODE (base) == IMAGPART_EXPR - || TREE_CODE (base) == BIT_FIELD_REF) - base = TREE_OPERAND (base, 0); - - if (TREE_CODE (base) == MEM_REF - && TREE_CODE (TREE_OPERAND (base, 0)) == ADDR_EXPR) - base = TREE_OPERAND (TREE_OPERAND (base, 0), 0); - if (DECL_P (base)) - { - if (CODE_CONTAINS_STRUCT (TREE_CODE (base), TS_DECL_WITH_VIS)) - MEM_NOTRAP_P (ref) = !DECL_WEAK (base); - else - MEM_NOTRAP_P (ref) = 1; - } - else if (TREE_CODE (base) == INDIRECT_REF - || TREE_CODE (base) == MEM_REF - || TREE_CODE (base) == TARGET_MEM_REF - || TREE_CODE (base) == ARRAY_REF - || TREE_CODE (base) == ARRAY_RANGE_REF) - MEM_NOTRAP_P (ref) = TREE_THIS_NOTRAP (base); - - base = get_base_address (base); + /* Note whether this expression can trap. */ + MEM_NOTRAP_P (ref) = !tree_could_trap_p (t); + + base = get_base_address (t); if (base && DECL_P (base) && TREE_READONLY (base) && (TREE_STATIC (base) || DECL_EXTERNAL (base)) diff --git a/gcc/except.c b/gcc/except.c index 2a25a3bd5b3..3e2bbfb1f75 100644 --- a/gcc/except.c +++ b/gcc/except.c @@ -3194,7 +3194,7 @@ dump_eh_tree (FILE * out, struct function *fun) } else { - for (lp = i->landing_pads; lp ; lp = lp->next_lp); + for (lp = i->landing_pads; lp ; lp = lp->next_lp) { fprintf (out, "{%i,", lp->index); if (lp->landing_pad) diff --git a/gcc/explow.c b/gcc/explow.c index 836f244b3a1..2a182065bca 100644 --- a/gcc/explow.c +++ b/gcc/explow.c @@ -1148,6 +1148,7 @@ allocate_dynamic_stack_space (rtx size, unsigned size_align, { HOST_WIDE_INT stack_usage_size = -1; rtx final_label, final_target, target; + unsigned extra_align = 0; bool must_align; /* If we're asking for zero bytes, it doesn't matter what we point @@ -1231,21 +1232,25 @@ allocate_dynamic_stack_space (rtx size, unsigned size_align, that might result from the alignment operation. */ must_align = (crtl->preferred_stack_boundary < required_align); -#if defined (STACK_DYNAMIC_OFFSET) || defined (STACK_POINTER_OFFSET) - must_align = true; -#endif - if (must_align) { - unsigned extra, extra_align; - if (required_align > PREFERRED_STACK_BOUNDARY) extra_align = PREFERRED_STACK_BOUNDARY; else if (required_align > STACK_BOUNDARY) extra_align = STACK_BOUNDARY; else extra_align = BITS_PER_UNIT; - extra = (required_align - extra_align) / BITS_PER_UNIT; + } + + /* ??? STACK_POINTER_OFFSET is always defined now. */ +#if defined (STACK_DYNAMIC_OFFSET) || defined (STACK_POINTER_OFFSET) + must_align = true; + extra_align = BITS_PER_UNIT; +#endif + + if (must_align) + { + unsigned extra = (required_align - extra_align) / BITS_PER_UNIT; size = plus_constant (size, extra); size = force_operand (size, NULL_RTX); diff --git a/gcc/expmed.c b/gcc/expmed.c index 24aedccde9e..f17abb53568 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -1,7 +1,8 @@ /* Medium-level subroutines: convert bit-field store and extract and shifts, multiplies and divides to rtl instructions. Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, + 2011 Free Software Foundation, Inc. This file is part of GCC. @@ -3188,12 +3189,17 @@ expand_widening_mult (enum machine_mode mode, rtx op0, rtx op1, rtx target, int unsignedp, optab this_optab) { bool speed = optimize_insn_for_speed_p (); + rtx cop1; if (CONST_INT_P (op1) - && (INTVAL (op1) >= 0 + && GET_MODE (op0) != VOIDmode + && (cop1 = convert_modes (mode, GET_MODE (op0), op1, + this_optab == umul_widen_optab)) + && CONST_INT_P (cop1) + && (INTVAL (cop1) >= 0 || GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)) { - HOST_WIDE_INT coeff = INTVAL (op1); + HOST_WIDE_INT coeff = INTVAL (cop1); int max_cost; enum mult_variant variant; struct algorithm algorithm; diff --git a/gcc/expr.c b/gcc/expr.c index dfcaefb4271..7441548884e 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -1,6 +1,6 @@ /* Convert tree expression to rtl instructions, for GNU compiler. Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GCC. @@ -7631,10 +7631,10 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode, if (optab_handler (this_optab, mode) != CODE_FOR_nothing) { if (TYPE_UNSIGNED (TREE_TYPE (treeop0))) - expand_operands (treeop0, treeop1, subtarget, &op0, &op1, + expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1, EXPAND_NORMAL); else - expand_operands (treeop0, treeop1, subtarget, &op1, &op0, + expand_operands (treeop0, treeop1, NULL_RTX, &op1, &op0, EXPAND_NORMAL); goto binop3; } @@ -7652,7 +7652,8 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode, optab other_optab = zextend_p ? smul_widen_optab : umul_widen_optab; this_optab = zextend_p ? umul_widen_optab : smul_widen_optab; - if (mode == GET_MODE_2XWIDER_MODE (innermode)) + if (mode == GET_MODE_2XWIDER_MODE (innermode) + && TREE_CODE (treeop0) != INTEGER_CST) { if (optab_handler (this_optab, mode) != CODE_FOR_nothing) { diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index a51003c54b0..8bf90a95b04 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,26 @@ +2011-01-18 Janus Weil <janus@gcc.gnu.org> + + PR fortran/47240 + * resolve.c (expression_rank): Fix rank of procedure poiner components. + * trans-expr.c (gfc_conv_procedure_call): Take care of procedure + pointer components as actual arguments. + +2011-01-17 Jakub Jelinek <jakub@redhat.com> + + PR fortran/47331 + * gfortran.h (struct gfc_omp_saved_state): New type. + (gfc_omp_save_and_clear_state, gfc_omp_restore_state): New prototypes. + * resolve.c (resolve_global_procedure): Call it around gfc_resolve + call. + * openmp.c (gfc_omp_save_and_clear_state, gfc_omp_restore_state): New + functions. + +2011-01-17 Tobias Burnus <burnus@net-b.de> + + PR fortran/47327 + * invoke.texi (Options to request or suppress errors + and warnings): Fix cross link. + 2011-01-15 Tobias Burnus <burnus@net-b.de> * gfortran.texi: Update Fortran 2003 Status section. diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index 2622f22fd85..ebba2a814fb 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -2651,11 +2651,14 @@ void gfc_free_case_list (gfc_case *); gfc_expr *gfc_get_parentheses (gfc_expr *); /* openmp.c */ +struct gfc_omp_saved_state { void *ptrs[2]; int ints[1]; }; void gfc_free_omp_clauses (gfc_omp_clauses *); void gfc_resolve_omp_directive (gfc_code *, gfc_namespace *); void gfc_resolve_do_iterator (gfc_code *, gfc_symbol *); void gfc_resolve_omp_parallel_blocks (gfc_code *, gfc_namespace *); void gfc_resolve_omp_do_blocks (gfc_code *, gfc_namespace *); +void gfc_omp_save_and_clear_state (struct gfc_omp_saved_state *); +void gfc_omp_restore_state (struct gfc_omp_saved_state *); /* expr.c */ void gfc_free_actual_arglist (gfc_actual_arglist *); diff --git a/gcc/fortran/invoke.texi b/gcc/fortran/invoke.texi index ae11356f834..291d1e7b7c4 100644 --- a/gcc/fortran/invoke.texi +++ b/gcc/fortran/invoke.texi @@ -865,7 +865,7 @@ off via @option{-Wno-align-commons}. See also @option{-falign-commons}. Turns all warnings into errors. @end table -@xref{Error and Warning Options,,Options to Request or Suppress Errors and +@xref{Warning Options,,Options to Request or Suppress Errors and Warnings, gcc,Using the GNU Compiler Collection (GCC)}, for information on more options offered by the GBE shared by @command{gfortran}, @command{gcc} and other GNU compilers. diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c index 6e8182118ce..24e32eb5d04 100644 --- a/gcc/fortran/openmp.c +++ b/gcc/fortran/openmp.c @@ -1390,6 +1390,31 @@ gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns) } +/* Save and clear openmp.c private state. */ + +void +gfc_omp_save_and_clear_state (struct gfc_omp_saved_state *state) +{ + state->ptrs[0] = omp_current_ctx; + state->ptrs[1] = omp_current_do_code; + state->ints[0] = omp_current_do_collapse; + omp_current_ctx = NULL; + omp_current_do_code = NULL; + omp_current_do_collapse = 0; +} + + +/* Restore openmp.c private state from the saved state. */ + +void +gfc_omp_restore_state (struct gfc_omp_saved_state *state) +{ + omp_current_ctx = (struct omp_context *) state->ptrs[0]; + omp_current_do_code = (gfc_code *) state->ptrs[1]; + omp_current_do_collapse = state->ints[0]; +} + + /* Note a DO iterator variable. This is special in !$omp parallel construct, where they are predetermined private. */ diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c index a1c991794b0..f2e722320dd 100644 --- a/gcc/fortran/resolve.c +++ b/gcc/fortran/resolve.c @@ -2011,11 +2011,14 @@ resolve_global_procedure (gfc_symbol *sym, locus *where, if (!gsym->ns->resolved) { gfc_dt_list *old_dt_list; + struct gfc_omp_saved_state old_omp_state; /* Stash away derived types so that the backend_decls do not get mixed up. */ old_dt_list = gfc_derived_types; gfc_derived_types = NULL; + /* And stash away openmp state. */ + gfc_omp_save_and_clear_state (&old_omp_state); gfc_resolve (gsym->ns); @@ -2025,6 +2028,8 @@ resolve_global_procedure (gfc_symbol *sym, locus *where, /* Restore the derived types of this namespace. */ gfc_derived_types = old_dt_list; + /* And openmp state. */ + gfc_omp_restore_state (&old_omp_state); } /* Make sure that translation for the gsymbol occurs before @@ -4858,6 +4863,10 @@ expression_rank (gfc_expr *e) for (ref = e->ref; ref; ref = ref->next) { + if (ref->type == REF_COMPONENT && ref->u.c.component->attr.proc_pointer + && ref->u.c.component->attr.function && !ref->next) + rank = ref->u.c.component->as ? ref->u.c.component->as->rank : 0; + if (ref->type != REF_ARRAY) continue; diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c index 42e259354d1..ec1e848509c 100644 --- a/gcc/fortran/trans-expr.c +++ b/gcc/fortran/trans-expr.c @@ -3043,8 +3043,9 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, && fsym->attr.flavor != FL_PROCEDURE) || (fsym->attr.proc_pointer && !(e->expr_type == EXPR_VARIABLE - && e->symtree->n.sym->attr.dummy)) - || (e->expr_type == EXPR_VARIABLE + && e->symtree->n.sym->attr.dummy)) + || (fsym->attr.proc_pointer + && e->expr_type == EXPR_VARIABLE && gfc_is_proc_ptr_comp (e, NULL)) || fsym->attr.allocatable)) { diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index a11e3d6fa17..819fb616452 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -10609,6 +10609,10 @@ Struct_construction_expression::do_determine_type(const Type_context*) (*pv)->determine_type(&subcontext); } } + // Extra values are an error we will report elsewhere; we still want + // to determine the type to avoid knockon errors. + for (; pv != this->vals_->end(); ++pv) + (*pv)->determine_type_no_context(); } // Check types. diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index 8bb2b72a5a7..bbf217abacc 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -482,6 +482,15 @@ bool Type::are_assignable(const Type* lhs, const Type* rhs, std::string* reason) { // Do some checks first. Make sure the types are defined. + if (rhs != NULL + && rhs->forwarded()->forward_declaration_type() == NULL + && rhs->is_void_type()) + { + if (reason != NULL) + *reason = "non-value used as value"; + return false; + } + if (lhs != NULL && lhs->forwarded()->forward_declaration_type() == NULL) { // Any value may be assigned to the blank identifier. @@ -3745,15 +3754,29 @@ Struct_type::fill_in_tree(Gogo* gogo, tree type) { tree field_trees = NULL_TREE; tree* pp = &field_trees; + bool has_pointer = false; for (Struct_field_list::const_iterator p = this->fields_->begin(); p != this->fields_->end(); ++p) { std::string name = Gogo::unpack_hidden_name(p->field_name()); tree name_tree = get_identifier_with_length(name.data(), name.length()); - tree field_type_tree = p->type()->get_tree(gogo); - if (field_type_tree == error_mark_node) - return error_mark_node; + + // Don't follow pointers yet, so that we don't get confused by a + // pointer to an array of this struct type. + tree field_type_tree; + if (p->type()->points_to() != NULL) + { + field_type_tree = ptr_type_node; + has_pointer = true; + } + else + { + field_type_tree = p->type()->get_tree(gogo); + if (field_type_tree == error_mark_node) + return error_mark_node; + } + tree field = build_decl(p->location(), FIELD_DECL, name_tree, field_type_tree); DECL_CONTEXT(field) = type; @@ -3765,6 +3788,18 @@ Struct_type::fill_in_tree(Gogo* gogo, tree type) layout_type(type); + if (has_pointer) + { + tree field = field_trees; + for (Struct_field_list::const_iterator p = this->fields_->begin(); + p != this->fields_->end(); + ++p, field = DECL_CHAIN(field)) + { + if (p->type()->points_to() != NULL) + TREE_TYPE(field) = p->type()->get_tree(gogo); + } + } + return type; } @@ -4848,7 +4883,7 @@ Array_type::array_type_descriptor(Gogo* gogo, Named_type* name) ++p; gcc_assert(p->field_name() == "len"); - vals->push_back(this->length_); + vals->push_back(Expression::make_cast(p->type(), this->length_, bloc)); ++p; gcc_assert(p == fields->end()); diff --git a/gcc/melt/warmelt-outobj.melt b/gcc/melt/warmelt-outobj.melt index 962d427130b..a8afb22f8fc 100644 --- a/gcc/melt/warmelt-outobj.melt +++ b/gcc/melt/warmelt-outobj.melt @@ -6429,7 +6429,7 @@ melt_scanning (melt_ptr_t p) (add2sbuf_string outbuf mapgetfun) (add2sbuf_strconst outbuf " (melt_ptr_t map_p, ") (add2sbuf_string outbuf cname) - (add2sbuf_strconst outbuf "attr) {") + (add2sbuf_strconst outbuf " attr) {") (add2sbuf_indentnl outbuf 2) (add2sbuf_strconst outbuf "if (!map_p || !attr ") (add2sbuf_indentnl outbuf 2) @@ -6453,7 +6453,7 @@ melt_scanning (melt_ptr_t p) (add2sbuf_string outbuf mapputfun) (add2sbuf_strconst outbuf " (melt_ptr_t map_p, ") (add2sbuf_string outbuf cname) - (add2sbuf_strconst outbuf "attr, melt_ptr_t valu_p) {") + (add2sbuf_strconst outbuf " attr, melt_ptr_t valu_p) {") (add2sbuf_indentnl outbuf 2) (add2sbuf_strconst outbuf "if (!map_p || !attr || !valu_p") (add2sbuf_indentnl outbuf 2) @@ -6477,7 +6477,7 @@ melt_scanning (melt_ptr_t p) (add2sbuf_string outbuf mapremovefun) (add2sbuf_strconst outbuf " (melt_ptr_t map_p, ") (add2sbuf_string outbuf cname) - (add2sbuf_strconst outbuf "attr, melt_ptr_t valu_p) {") + (add2sbuf_strconst outbuf " attr, melt_ptr_t valu_p) {") (add2sbuf_indentnl outbuf 2) (add2sbuf_strconst outbuf "if (!map_p || !attr") (add2sbuf_indentnl outbuf 2) diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog index 42f50c2fa13..7b424391dd0 100644 --- a/gcc/objc/ChangeLog +++ b/gcc/objc/ChangeLog @@ -1,3 +1,9 @@ +2011-01-17 Nicola Pero <nicola.pero@meta-innovation.com> + + PR objc/47314 + * objc-act.c (finish_objc): When calling check_duplicates to check + duplicated instance methods, set 'is_class' to 0, not 1. + 2011-01-14 Ben Elliston <bje@au.ibm.com> PR 19162 diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index cfbdb6f6134..33d39b222f4 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -12986,7 +12986,7 @@ finish_objc (void) for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next) check_duplicates (hsh, 0, 1); for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next) - check_duplicates (hsh, 0, 1); + check_duplicates (hsh, 0, 0); } } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d95034fff44..550aee1cef6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,6 +1,97 @@ +2011-01-19 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/47290 + * g++.dg/torture/pr47290.C: New test. + +2011-01-18 Janus Weil <janus@gcc.gnu.org> + + PR fortran/47240 + * gfortran.dg/proc_ptr_comp_29.f90: New. + +2011-01-18 Dominique d'Humieres <dominiq@lps.ens.fr> + + PR testsuite/41146 + * gcc.target/powerpc/asm-es-2.c: Adjust regular expression for + powerpc-apple-darwin9. + +2011-01-18 Jakub Jelinek <jakub@redhat.com> + + PR rtl-optimization/47299 + * gcc.c-torture/execute/pr47299.c: New test. + +2011-01-17 Jason Merrill <jason@redhat.com> + + * g++.dg/cpp0x/constexpr-virtual.C: New. + +2011-01-17 Jakub Jelinek <jakub@redhat.com> + + PR fortran/47331 + * gfortran.dg/gomp/pr47331.f90: New test. + +2011-01-17 Nicola Pero <nicola.pero@meta-innovation.com> + + PR objc/47314 + * objc.dg/selector-warn-1.m: New. + * obj-c++.dg/selector-warn-1.mm: New. + +2011-01-17 Richard Sandiford <rdsandiford@googlemail.com> + + * gcc.dg/tree-ssa/vrp51.c: Prefix each "bug." string with "vrp.". + Update dg-final accordingly. + +2011-01-17 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * g++.old-deja/g++.other/init19.C: Don't XFAIL on mips-sgi-irix*. + +2011-01-17 Andreas Krebbel <Andreas.Krebbel@de.ibm.com> + + * gcc.dg/guality/pr36728-1.c: Replace XFAIL for s390(x) with a + target check. + * gcc.dg/guality/pr36728-2.c: Likewise. + +2011-01-17 Richard Guenther <rguenther@suse.de> + + PR tree-optimization/47313 + * g++.dg/torture/pr47313.C: New testcase. + +2011-01-17 H.J. Lu <hongjiu.lu@intel.com> + + PR target/47318 + * gcc.target/i386/avx-vmaskmovpd-1.c: New. + * gcc.target/i386/avx-vmaskmovpd-2.c: Likewise. + * gcc.target/i386/avx-vmaskmovps-1.c: Likewise. + * gcc.target/i386/avx-vmaskmovps-1.c: Likewise. + + * gcc.target/i386/avx-vmaskmovpd-256-1.c (avx_test): Load mask + as __m256i. + * gcc.target/i386/avx-vmaskmovpd-256-2.c (avx_test): Likewise. + * gcc.target/i386/avx-vmaskmovps-256-1.c (avx_test): Likewise. + * gcc.target/i386/avx-vmaskmovps-256-2.c (avx_test): Likewise. + +2011-01-17 Richard Guenther <rguenther@suse.de> + + PR tree-optimization/45967 + * gcc.dg/torture/pr45967-2.c: New testcase. + * gcc.dg/torture/pr45967-3.c: Likewise. + +2011-01-16 John David Anglin <dave.anglin@nrc-cnrc.gc.ca> + + PR testsuite/47325 + g++.dg/ext/pr47213.C: Require visibility. + +2011-01-16 Richard Sandiford <rdsandiford@googlemail.com> + + * gcc.dg/fixed-point/composite-type.c: Pass -Wno-unused. + * gcc.dg/fixed-point/struct-union.c: Update error messages. + +2011-01-16 Richard Sandiford <rdsandiford@googlemail.com> + + * gcc.c-torture/execute/20101011-1.c: Skip test for MIPS16 + Linux-based targets. + 2011-01-13 Jan Hubicka <jh@suse.cz> - PR tree-optimization/47276 + PR tree-optimization/47276 * gcc.dg/pr47276.c: New testcase. 2011-01-15 Giovanni Funchal <gafunchal@gmail.com> @@ -126,7 +217,7 @@ * objc-obj-c++-shared/Object1-implementation.h: Add copyright header. Amend implementation to use a TEST_SUITE_ADDITIONS category for both GNU and NeXT runtimes. - * objc-obj-c++-shared/Object1.mm: Remove redundant header, update + * objc-obj-c++-shared/Object1.mm: Remove redundant header, update comments. * objc-obj-c++-shared/Object1.m: Likewise. * objc.dg/encode-3.m: Update header use. Amend to be API2 compatible. diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-virtual.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-virtual.C new file mode 100644 index 00000000000..448ecb1dc70 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-virtual.C @@ -0,0 +1,14 @@ +// PR c++/47067 +// { dg-options -std=c++0x } + +struct X { + virtual void x(); + virtual ~X(); +}; + +struct Y { + virtual void y(); + virtual ~Y(); +}; + +struct Z: X, Y {} z; diff --git a/gcc/testsuite/g++.dg/ext/pr47213.C b/gcc/testsuite/g++.dg/ext/pr47213.C index b39013c8f58..193007e8353 100644 --- a/gcc/testsuite/g++.dg/ext/pr47213.C +++ b/gcc/testsuite/g++.dg/ext/pr47213.C @@ -1,4 +1,5 @@ // { dg-do compile } +// { dg-require-visibility "" } // { dg-options "-fvisibility-ms-compat" } #include <typeinfo> diff --git a/gcc/testsuite/g++.dg/torture/pr47290.C b/gcc/testsuite/g++.dg/torture/pr47290.C new file mode 100644 index 00000000000..b739de5b749 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr47290.C @@ -0,0 +1,19 @@ +// PR tree-optimization/47290 +// { dg-do compile } + +struct V +{ + V (int = 0); + ~V () + { + for (;;) + ; + } + int size (); +}; + +struct S +{ + V a, b; + S () : b (a.size ()) {} +} s; diff --git a/gcc/testsuite/g++.dg/torture/pr47313.C b/gcc/testsuite/g++.dg/torture/pr47313.C new file mode 100644 index 00000000000..c10f558a3eb --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr47313.C @@ -0,0 +1,53 @@ +// { dg-do compile } + +namespace internal { + template < class DSC, bool Const > struct CC_iterator { + typedef CC_iterator iterator; + typedef typename DSC::value_type value_type; + typedef const value_type* pointer; + CC_iterator () ; + CC_iterator (const iterator &it) { + } + pointer p; + pointer operator->() const ; + }; +} +template < class T > struct Compact_container { + typedef Compact_container <T> Self; + typedef T value_type; + typedef internal::CC_iterator<Self, false> iterator; +}; +template < typename TDS = void > struct Periodic_3_triangulation_ds_cell_base_3 { + typedef typename TDS::Vertex_handle Vertex_handle; + const Vertex_handle& vertex(int i) const { + } +}; +struct Triangulation_data_structure_3 { + typedef Triangulation_data_structure_3 Tds; + typedef Periodic_3_triangulation_ds_cell_base_3<Tds> Cell; + typedef Compact_container<Cell> Cell_range; + typedef Compact_container<int> Vertex_range; + typedef typename Cell_range::iterator Cell_handle; + typedef typename Vertex_range::iterator Vertex_handle; +}; +typedef Triangulation_data_structure_3 TDS1; +template < class > struct Periodic_3_Delaunay_triangulation_3 { + typedef TDS1::Vertex_handle Vertex_handle; + typedef TDS1::Cell_handle Cell_handle; + int compare_distance() const { + } + Vertex_handle nearest_vertex() const; +}; +template < class Tds > typename Periodic_3_Delaunay_triangulation_3<Tds>::Vertex_handle Periodic_3_Delaunay_triangulation_3<Tds>::nearest_vertex() const { + Cell_handle c ; + Vertex_handle nearest = c->vertex(0); + nearest = (compare_distance() == -1) ? nearest : c->vertex(0); + return nearest; +} +typedef Periodic_3_Delaunay_triangulation_3<TDS1> PDT1; +struct Periodic_3_triangulation_hierarchy_3 : PDT1 { + Vertex_handle nearest_vertex() const; +}; +Periodic_3_triangulation_hierarchy_3::Vertex_handle Periodic_3_triangulation_hierarchy_3:: nearest_vertex() const { + return PDT1::nearest_vertex(); +} diff --git a/gcc/testsuite/g++.old-deja/g++.other/init19.C b/gcc/testsuite/g++.old-deja/g++.other/init19.C index 1c686841243..bcbe82287dc 100644 --- a/gcc/testsuite/g++.old-deja/g++.other/init19.C +++ b/gcc/testsuite/g++.old-deja/g++.other/init19.C @@ -1,4 +1,4 @@ -// { dg-do run { xfail { { ! cxa_atexit } && { ! *-*-solaris2* } } } } +// { dg-do run { xfail { { ! cxa_atexit } && { ! { mips-sgi-irix* *-*-solaris2* } } } } } #include <stdlib.h> #define assert(x) do { if (! (x)) abort(); } while (0) diff --git a/gcc/testsuite/gcc.c-torture/execute/20101011-1.c b/gcc/testsuite/gcc.c-torture/execute/20101011-1.c index 077940548e1..7180e68b065 100644 --- a/gcc/testsuite/gcc.c-torture/execute/20101011-1.c +++ b/gcc/testsuite/gcc.c-torture/execute/20101011-1.c @@ -18,6 +18,10 @@ true of other bare-metal environments, so restrict the test to systems that use the Linux kernel. */ # define DO_TEST 0 +#elif defined (__mips16) && defined(__linux__) + /* Not all Linux kernels deal correctly the breakpoints generated by + MIPS16 divisions by zero. They show up as a SIGTRAP instead. */ +# define DO_TEST 0 #else # define DO_TEST 1 #endif diff --git a/gcc/testsuite/gcc.c-torture/execute/pr47299.c b/gcc/testsuite/gcc.c-torture/execute/pr47299.c new file mode 100644 index 00000000000..4f3d1f9cb12 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr47299.c @@ -0,0 +1,17 @@ +/* PR rtl-optimization/47299 */ + +extern void abort (void); + +__attribute__ ((noinline, noclone)) unsigned short +foo (unsigned char x) +{ + return x * 255; +} + +int +main () +{ + if (foo (0x40) != 0x3fc0) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/fixed-point/composite-type.c b/gcc/testsuite/gcc.dg/fixed-point/composite-type.c index 031de0e1104..5ae11981e26 100644 --- a/gcc/testsuite/gcc.dg/fixed-point/composite-type.c +++ b/gcc/testsuite/gcc.dg/fixed-point/composite-type.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-std=gnu99 -O -Wall" } */ +/* { dg-options "-std=gnu99 -O -Wall -Wno-unused" } */ /* C99 6.2.7: Compatible type and composite type. */ diff --git a/gcc/testsuite/gcc.dg/fixed-point/struct-union.c b/gcc/testsuite/gcc.dg/fixed-point/struct-union.c index 11477526652..93ed260b04c 100644 --- a/gcc/testsuite/gcc.dg/fixed-point/struct-union.c +++ b/gcc/testsuite/gcc.dg/fixed-point/struct-union.c @@ -34,22 +34,22 @@ union u h (union u u) void f() { - cs.f = 0.1r; /* { dg-error "assignment of read-only variable" } */ - cs.lf = 0.2lr; /* { dg-error "assignment of read-only variable" } */ + cs.f = 0.1r; /* { dg-error "assignment of member 'f' in read-only object" } */ + cs.lf = 0.2lr; /* { dg-error "assignment of member 'lf' in read-only object" } */ s.lf = 0.3lr; /* { dg-error "assignment of read-only member" } */ s.f = 0.4r; u.f = 0.5r; u.lf = 0.6lr; /* { dg-error "assignment of read-only member" } */ - u.cs.f = 0.7r; /* { dg-error "assignment of read-only member" } */ - u.cs.lf = 0.8lr; /* { dg-error "assignment of read-only member" } */ + u.cs.f = 0.7r; /* { dg-error "assignment of member 'f' in read-only object" } */ + u.cs.lf = 0.8lr; /* { dg-error "assignment of member 'lf' in read-only object" } */ - cu.f = 0.9r; /* { dg-error "assignment of read-only variable" } */ + cu.f = 0.9r; /* { dg-error "assignment of member 'f' in read-only object" } */ - cu.lf = 0.01lr; /* { dg-error "assignment of read-only variable" } */ - cu.cs.f = 0.02r; /* { dg-error "assignment of read-only variable" } */ - cu.cs.lf = 0.03lr; /* { dg-error "assignment of read-only variable" } */ + cu.lf = 0.01lr; /* { dg-error "assignment of member 'lf' in read-only object" } */ + cu.cs.f = 0.02r; /* { dg-error "assignment of member 'f' in read-only object" } */ + cu.cs.lf = 0.03lr; /* { dg-error "assignment of member 'lf' in read-only object" } */ /* f().x is a valid postfix expression but is not an lvalue if function f() returning a structure or union. */ diff --git a/gcc/testsuite/gcc.dg/guality/pr36728-1.c b/gcc/testsuite/gcc.dg/guality/pr36728-1.c index 33e25f45c1d..c4ad564e1dc 100644 --- a/gcc/testsuite/gcc.dg/guality/pr36728-1.c +++ b/gcc/testsuite/gcc.dg/guality/pr36728-1.c @@ -15,16 +15,22 @@ foo (int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7) return y; } -/* { dg-final { gdb-test 12 "arg1" "1" { xfail s390*-*-* } } } */ -/* { dg-final { gdb-test 12 "arg2" "2" { xfail s390*-*-* } } } */ +/* On s390(x) r2 and r3 are (depending on the optimization level) used + when adjusting the addresses in order to meet the alignment + requirements above. They usually hold the function arguments arg1 + and arg2. So it is expected that these values are unavailable in + some of these tests. */ + +/* { dg-final { gdb-test 12 "arg1" "1" { target { ! "s390*-*-*" } } } }*/ +/* { dg-final { gdb-test 12 "arg2" "2" { target { ! "s390*-*-*" } } } }*/ /* { dg-final { gdb-test 12 "arg3" "3" } } */ /* { dg-final { gdb-test 12 "arg4" "4" } } */ /* { dg-final { gdb-test 12 "arg5" "5" } } */ /* { dg-final { gdb-test 12 "arg6" "6" } } */ /* { dg-final { gdb-test 12 "arg7" "30" } } */ /* { dg-final { gdb-test 12 "y" "2" } } */ -/* { dg-final { gdb-test 14 "arg1" "1" { xfail s390*-*-* } } } */ -/* { dg-final { gdb-test 14 "arg2" "2" { xfail s390*-*-* } } } */ +/* { dg-final { gdb-test 14 "arg1" "1" { target { ! "s390*-*-*" } } } }*/ +/* { dg-final { gdb-test 14 "arg2" "2" { target { ! "s390*-*-*" } } } }*/ /* { dg-final { gdb-test 14 "arg3" "3" } } */ /* { dg-final { gdb-test 14 "arg4" "4" } } */ /* { dg-final { gdb-test 14 "arg5" "5" } } */ diff --git a/gcc/testsuite/gcc.dg/guality/pr36728-2.c b/gcc/testsuite/gcc.dg/guality/pr36728-2.c index 7072a8dddeb..a7c2de74791 100644 --- a/gcc/testsuite/gcc.dg/guality/pr36728-2.c +++ b/gcc/testsuite/gcc.dg/guality/pr36728-2.c @@ -15,16 +15,22 @@ foo (int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7) return y; } -/* { dg-final { gdb-test 12 "arg1" "1" { xfail s390*-*-* } } } */ -/* { dg-final { gdb-test 12 "arg2" "2" { xfail s390*-*-* } } } */ +/* On s390(x) r2 and r3 are (depending on the optimization level) used + when adjusting the addresses in order to meet the alignment + requirements above. They usually hold the function arguments arg1 + and arg2. So it is expected that these values are unavailable in + some of these tests. */ + +/* { dg-final { gdb-test 12 "arg1" "1" { target { ! "s390*-*-*" } } } } */ +/* { dg-final { gdb-test 12 "arg2" "2" { target { ! "s390*-*-*" } } } } */ /* { dg-final { gdb-test 12 "arg3" "3" } } */ /* { dg-final { gdb-test 12 "arg4" "4" } } */ /* { dg-final { gdb-test 12 "arg5" "5" } } */ /* { dg-final { gdb-test 12 "arg6" "6" } } */ /* { dg-final { gdb-test 12 "arg7" "30" } } */ /* { dg-final { gdb-test 12 "y" "2" } } */ -/* { dg-final { gdb-test 14 "arg1" "1" { xfail s390*-*-* } } } */ -/* { dg-final { gdb-test 14 "arg2" "2" { xfail s390*-*-* } } } */ +/* { dg-final { gdb-test 14 "arg1" "1" { target { ! "s390*-*-*" } } } } */ +/* { dg-final { gdb-test 14 "arg2" "2" { target { ! "s390*-*-*" } } } } */ /* { dg-final { gdb-test 14 "arg3" "3" } } */ /* { dg-final { gdb-test 14 "arg4" "4" } } */ /* { dg-final { gdb-test 14 "arg5" "5" } } */ diff --git a/gcc/testsuite/gcc.dg/torture/pr45967-2.c b/gcc/testsuite/gcc.dg/torture/pr45967-2.c new file mode 100644 index 00000000000..6959fd5e15c --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr45967-2.c @@ -0,0 +1,24 @@ +/* { dg-do run } */ + +extern void abort (void); +int b; +void +foo (void *p_, int *q) +{ + int *p; + int i; + for (i = 0; i < sizeof(int *); ++i) + ((char *)&p)[i] = ((char *)p_)[i]; + if (b) + p = q; + *p = 1; +} +int main() +{ + int i = 0, j; + int *p = &i; + foo (&p, &j); + if (i != 1) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr45967-3.c b/gcc/testsuite/gcc.dg/torture/pr45967-3.c new file mode 100644 index 00000000000..1a23a773b17 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr45967-3.c @@ -0,0 +1,21 @@ +/* { dg-do run } */ + +extern void abort (void); +void +foo (void *p_) +{ + int *p; + int i; + for (i = 0; i < sizeof(int *); ++i) + ((char *)&p)[i] = ((char *)p_)[i]; + *p = 1; +} +int main() +{ + int i = 0; + int *p = &i; + foo (&p); + if (i != 1) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp51.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp51.c index 66aa5ed6d6b..5f1cafb0a50 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/vrp51.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp51.c @@ -10,10 +10,10 @@ v4 (unsigned a, unsigned b) if (b < 0x0110) return; /* constant true. */ if (!__builtin_constant_p ((a|b) >= 0x01000)) - __asm__("bug.always.true"); + __asm__("vrp.bug.always.true"); /* VRP must not think that this is constant. */ if (__builtin_constant_p ((a|b) >= 0x10000)) - __asm__("bug.not.always.true"); + __asm__("vrp.bug.not.always.true"); } void @@ -23,13 +23,13 @@ u4 (unsigned n) if (n < 0x10101) return; /* always true. */ if (!__builtin_constant_p (n & 0x00100)) - __asm__("bug.always.true"); + __asm__("vrp.bug.always.true"); /* VRP must not think that this is constant true. */ if (__builtin_constant_p (n & 0x00001)) - __asm__("bug.not.always.true"); + __asm__("vrp.bug.not.always.true"); /* Out of range, always evaluates to constant false. */ if (!__builtin_constant_p (n & 0x01000)) - __asm__("bug.always.false"); + __asm__("vrp.bug.always.false"); } void @@ -38,7 +38,7 @@ u5 (unsigned n) struct s {unsigned exp:8;} x; x.exp = n; if (__builtin_constant_p(((n + 1) & 255) > 1)) - __asm__("bug.not.always.true"); + __asm__("vrp.bug.not.always.true"); } void @@ -49,10 +49,10 @@ v5 (int a, int b) if (b < 0x0110) return; /* constant true. */ if (!__builtin_constant_p ((a|b) >= 0x01000)) - __asm__("bug.always.true"); + __asm__("vrp.bug.always.true"); /* VRP must not think that this is always true. */ if (__builtin_constant_p ((a|b) >= 0x10000)) - __asm__("bug.not.always.true"); + __asm__("vrp.bug.not.always.true"); } -/* { dg-final { scan-assembler-not "bug\." } } */ +/* { dg-final { scan-assembler-not "vrp\\\.bug\\\." } } */ diff --git a/gcc/testsuite/gcc.target/i386/avx-vmaskmovpd-1.c b/gcc/testsuite/gcc.target/i386/avx-vmaskmovpd-1.c new file mode 100644 index 00000000000..6204ebd2872 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx-vmaskmovpd-1.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ +/* { dg-require-effective-target avx } */ +/* { dg-options "-O2 -mavx" } */ + +#include "avx-check.h" + +#ifndef MASK +#define MASK 7 +#endif + +#define mask_v(pos) (((MASK & (0x1ULL << (pos))) >> (pos)) << 63) + +void static +avx_test (void) +{ + int i; + long long m[2] = {mask_v(0), mask_v(1)}; + double s[2] = {1.1, 2.2}; + union128d u; + union128i_q mask; + double e[2] = {0.0}; + + mask.x = _mm_loadu_si128 ((__m128i *)m); + u.x = _mm_maskload_pd (s, mask.x); + + for (i = 0 ; i < 2; i++) + e[i] = m[i] ? s[i] : 0; + + if (check_union128d (u, e)) + abort (); +} diff --git a/gcc/testsuite/gcc.target/i386/avx-vmaskmovpd-2.c b/gcc/testsuite/gcc.target/i386/avx-vmaskmovpd-2.c new file mode 100644 index 00000000000..6bc620755f9 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx-vmaskmovpd-2.c @@ -0,0 +1,33 @@ +/* { dg-do run } */ +/* { dg-require-effective-target avx } */ +/* { dg-options "-O2 -mavx" } */ + +#include "avx-check.h" + +#ifndef MASK +#define MASK 6 +#endif + +#define mask_v(pos) (((MASK & (0x1ULL << (pos))) >> (pos)) << 63) + +void static +avx_test (void) +{ + int i; + long long m[2] = {mask_v(0), mask_v(1)}; + double s[2] = {1.1, 2.2}; + double e[2] = {0.0}; + double d[2] = {0.0}; + union128d src; + union128i_q mask; + + src.x = _mm_loadu_pd (s); + mask.x = _mm_loadu_si128 ((__m128i *)m); + _mm_maskstore_pd (d, mask.x, src.x); + + for (i = 0 ; i < 2; i++) + e[i] = m[i] ? s[i] : 0; + + if (checkVd (d, e, 2)) + abort (); +} diff --git a/gcc/testsuite/gcc.target/i386/avx-vmaskmovpd-256-1.c b/gcc/testsuite/gcc.target/i386/avx-vmaskmovpd-256-1.c index f29826bbbd4..e591c05c8e8 100644 --- a/gcc/testsuite/gcc.target/i386/avx-vmaskmovpd-256-1.c +++ b/gcc/testsuite/gcc.target/i386/avx-vmaskmovpd-256-1.c @@ -14,12 +14,13 @@ void static avx_test (void) { int i; - long long m[8] = {mask_v(0), mask_v(1), mask_v(2), mask_v(3)}; + long long m[4] = {mask_v(0), mask_v(1), mask_v(2), mask_v(3)}; double s[4] = {1.1, 2.2, 3.3, 4.4}; - union256d u, mask; + union256d u; + union256i_q mask; double e [4] = {0.0}; - mask.x = _mm256_loadu_pd ((double*)m); + mask.x = _mm256_loadu_si256 ((__m256i *)m); u.x = _mm256_maskload_pd (s, mask.x); for (i = 0 ; i < 4; i++) diff --git a/gcc/testsuite/gcc.target/i386/avx-vmaskmovpd-256-2.c b/gcc/testsuite/gcc.target/i386/avx-vmaskmovpd-256-2.c index 1e574b6993b..5df2f94ee5f 100644 --- a/gcc/testsuite/gcc.target/i386/avx-vmaskmovpd-256-2.c +++ b/gcc/testsuite/gcc.target/i386/avx-vmaskmovpd-256-2.c @@ -18,10 +18,11 @@ avx_test (void) double s[4] = {1.1, 2.2, 3.3, 4.4}; double e [4] = {0.0}; double d [4] = {0.0}; - union256d src, mask; + union256d src; + union256i_q mask; src.x = _mm256_loadu_pd (s); - mask.x = _mm256_loadu_pd ((double*)m); + mask.x = _mm256_loadu_si256 ((__m256i *)m); _mm256_maskstore_pd (d, mask.x, src.x); for (i = 0 ; i < 4; i++) diff --git a/gcc/testsuite/gcc.target/i386/avx-vmaskmovps-1.c b/gcc/testsuite/gcc.target/i386/avx-vmaskmovps-1.c new file mode 100644 index 00000000000..360a04dbaaa --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx-vmaskmovps-1.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ +/* { dg-require-effective-target avx } */ +/* { dg-options "-O2 -mavx" } */ + +#include "avx-check.h" + +#ifndef MASK +#define MASK 134 +#endif + +#define mask_v(pos) (((MASK & (0x1 << (pos))) >> (pos)) << 31) + +void static +avx_test (void) +{ + int i; + int m[4] = {mask_v(0), mask_v(1), mask_v(2), mask_v(3)}; + float s[4] = {1,2,3,4}; + union128 u; + union128i_d mask; + float e[4] = {0.0}; + + mask.x = _mm_loadu_si128 ((__m128i *)m); + u.x = _mm_maskload_ps (s, mask.x); + + for (i = 0 ; i < 4; i++) + e[i] = m[i] ? s[i] : 0; + + if (check_union128 (u, e)) + abort (); +} diff --git a/gcc/testsuite/gcc.target/i386/avx-vmaskmovps-2.c b/gcc/testsuite/gcc.target/i386/avx-vmaskmovps-2.c new file mode 100644 index 00000000000..3dde96557c0 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx-vmaskmovps-2.c @@ -0,0 +1,33 @@ +/* { dg-do run } */ +/* { dg-require-effective-target avx } */ +/* { dg-options "-O2 -mavx" } */ + +#include "avx-check.h" + +#ifndef MASK +#define MASK 214 +#endif + +#define mask_v(pos) (((MASK & (0x1 << (pos))) >> (pos)) << 31) + +void static +avx_test (void) +{ + int i; + int m[4] = {mask_v(0), mask_v(1), mask_v(2), mask_v(3)}; + float s[4] = {1,2,3,4}; + union128 src; + union128i_d mask; + float e[4] = {0.0}; + float d[4] = {0.0}; + + src.x = _mm_loadu_ps (s); + mask.x = _mm_loadu_si128 ((__m128i *)m); + _mm_maskstore_ps (d, mask.x, src.x); + + for (i = 0 ; i < 4; i++) + e[i] = m[i] ? s[i] : 0; + + if (checkVf (d, e, 4)) + abort (); +} diff --git a/gcc/testsuite/gcc.target/i386/avx-vmaskmovps-256-1.c b/gcc/testsuite/gcc.target/i386/avx-vmaskmovps-256-1.c index 9e6c7f91d91..647ce3f6e61 100644 --- a/gcc/testsuite/gcc.target/i386/avx-vmaskmovps-256-1.c +++ b/gcc/testsuite/gcc.target/i386/avx-vmaskmovps-256-1.c @@ -16,10 +16,11 @@ avx_test (void) int i; int m[8] = {mask_v(0), mask_v(1), mask_v(2), mask_v(3), mask_v(4), mask_v(5), mask_v(6), mask_v(7)}; float s[8] = {1,2,3,4,5,6,7,8}; - union256 u, mask; + union256 u; + union256i_d mask; float e [8] = {0.0}; - mask.x = _mm256_loadu_ps ((float*)m); + mask.x = _mm256_loadu_si256 ((__m256i *)m); u.x = _mm256_maskload_ps (s, mask.x); for (i = 0 ; i < 8; i++) diff --git a/gcc/testsuite/gcc.target/i386/avx-vmaskmovps-256-2.c b/gcc/testsuite/gcc.target/i386/avx-vmaskmovps-256-2.c index 90d91a06a6d..016904d4638 100644 --- a/gcc/testsuite/gcc.target/i386/avx-vmaskmovps-256-2.c +++ b/gcc/testsuite/gcc.target/i386/avx-vmaskmovps-256-2.c @@ -16,12 +16,13 @@ avx_test (void) int i; int m[8] = {mask_v(0), mask_v(1), mask_v(2), mask_v(3), mask_v(4), mask_v(5), mask_v(6), mask_v(7)}; float s[8] = {1,2,3,4,5,6,7,8}; - union256 src, mask; + union256 src; + union256i_d mask; float e [8] = {0.0}; float d [8] = {0.0}; src.x = _mm256_loadu_ps (s); - mask.x = _mm256_loadu_ps ((float *)m); + mask.x = _mm256_loadu_si256 ((__m256i *)m); _mm256_maskstore_ps (d, mask.x, src.x); for (i = 0 ; i < 8; i++) diff --git a/gcc/testsuite/gcc.target/powerpc/asm-es-2.c b/gcc/testsuite/gcc.target/powerpc/asm-es-2.c index 94c2883d18a..d2b46913b74 100644 --- a/gcc/testsuite/gcc.target/powerpc/asm-es-2.c +++ b/gcc/testsuite/gcc.target/powerpc/asm-es-2.c @@ -31,7 +31,7 @@ f4 (int *p) asm ("asm4 %0" : "=es" (p[100])); } -/* { dg-final { scan-assembler "asm1 3,4" } } */ -/* { dg-final { scan-assembler "asm2u 16\\(3\\)" } } */ -/* { dg-final { scan-assembler "asm3 0\\(3\\)" } } */ -/* { dg-final { scan-assembler "asm4 400\\(3\\)" } } */ +/* { dg-final { scan-assembler "asm1 %?r?3,%?r?4" } } */ +/* { dg-final { scan-assembler "asm2u 16\\(%?r?3\\)" } } */ +/* { dg-final { scan-assembler "asm3 0\\(%?r?3\\)" } } */ +/* { dg-final { scan-assembler "asm4 400\\(%?r?3\\)" } } */ diff --git a/gcc/testsuite/gfortran.dg/gomp/pr47331.f90 b/gcc/testsuite/gfortran.dg/gomp/pr47331.f90 new file mode 100644 index 00000000000..71713e02233 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/pr47331.f90 @@ -0,0 +1,24 @@ +! PR fortran/47331 +! { dg-do compile } +! { dg-options "-fopenmp -fwhole-file" } + +subroutine foo + !$omp parallel + call bar () + !$omp end parallel +end subroutine foo + +subroutine bar + integer :: k + do k=1,5 + call baz (k) + end do +end subroutine bar + +subroutine baz (k) + integer :: k +end subroutine + +program pr47331 + call foo +end program pr47331 diff --git a/gcc/testsuite/gfortran.dg/proc_ptr_comp_29.f90 b/gcc/testsuite/gfortran.dg/proc_ptr_comp_29.f90 new file mode 100644 index 00000000000..94c59cd1a3b --- /dev/null +++ b/gcc/testsuite/gfortran.dg/proc_ptr_comp_29.f90 @@ -0,0 +1,25 @@ +! { dg-do run } +! +! PR 47240: [F03] segfault with procedure pointer component +! +! Contributed by Martien Hulsen <m.a.hulsen@tue.nl> + + type t + procedure (fun), pointer, nopass :: p + end type + type(t) :: x + real, dimension(2) :: r + x%p => fun + r = evaluate (x%p) + if (r(1) /= 5 .and. r(2) /= 6) call abort() +contains + function fun () + real, dimension(2) :: fun + fun = (/ 5, 6 /) + end function + function evaluate ( dummy ) + real, dimension(2) :: evaluate + procedure(fun) :: dummy + evaluate = dummy () + end function +end diff --git a/gcc/testsuite/obj-c++.dg/selector-warn-1.mm b/gcc/testsuite/obj-c++.dg/selector-warn-1.mm new file mode 100644 index 00000000000..b4b308d7b70 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/selector-warn-1.mm @@ -0,0 +1,16 @@ +/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, January 2011. */ +/* { dg-options "-Wselector" } */ +/* { dg-do compile } */ + +#include <objc/objc.h> + +@interface RootObject +@end + +@interface MyObject : RootObject +- (void) method; /* { dg-message "found" } */ +@end + +@interface MyObject2 : RootObject +- (int) method; /* { dg-message "also found" } */ +@end /* { dg-warning "multiple selectors named .-method. found" } */ diff --git a/gcc/testsuite/objc.dg/selector-warn-1.m b/gcc/testsuite/objc.dg/selector-warn-1.m new file mode 100644 index 00000000000..b4b308d7b70 --- /dev/null +++ b/gcc/testsuite/objc.dg/selector-warn-1.m @@ -0,0 +1,16 @@ +/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, January 2011. */ +/* { dg-options "-Wselector" } */ +/* { dg-do compile } */ + +#include <objc/objc.h> + +@interface RootObject +@end + +@interface MyObject : RootObject +- (void) method; /* { dg-message "found" } */ +@end + +@interface MyObject2 : RootObject +- (int) method; /* { dg-message "also found" } */ +@end /* { dg-warning "multiple selectors named .-method. found" } */ diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c index 270d76d9480..65d0ff2f9fd 100644 --- a/gcc/tree-eh.c +++ b/gcc/tree-eh.c @@ -1,5 +1,5 @@ /* Exception handling semantics and decomposition for trees. - Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GCC. @@ -3724,6 +3724,42 @@ cleanup_empty_eh_unsplit (basic_block bb, edge e_out, eh_landing_pad lp) return false; } +/* Return true if edge E_FIRST is part of an empty infinite loop + or leads to such a loop through a series of single successor + empty bbs. */ + +static bool +infinite_empty_loop_p (edge e_first) +{ + bool inf_loop = false; + edge e; + + if (e_first->dest == e_first->src) + return true; + + e_first->src->aux = (void *) 1; + for (e = e_first; single_succ_p (e->dest); e = single_succ_edge (e->dest)) + { + gimple_stmt_iterator gsi; + if (e->dest->aux) + { + inf_loop = true; + break; + } + e->dest->aux = (void *) 1; + gsi = gsi_after_labels (e->dest); + if (!gsi_end_p (gsi) && is_gimple_debug (gsi_stmt (gsi))) + gsi_next_nondebug (&gsi); + if (!gsi_end_p (gsi)) + break; + } + e_first->src->aux = NULL; + for (e = e_first; e->dest->aux; e = single_succ_edge (e->dest)) + e->dest->aux = NULL; + + return inf_loop; +} + /* Examine the block associated with LP to determine if it's an empty handler for its EH region. If so, attempt to redirect EH edges to an outer region. Return true the CFG was updated in any way. This @@ -3763,7 +3799,7 @@ cleanup_empty_eh (eh_landing_pad lp) if (gsi_end_p (gsi)) { /* For the degenerate case of an infinite loop bail out. */ - if (e_out->dest == bb) + if (infinite_empty_loop_p (e_out)) return false; return cleanup_empty_eh_unsplit (bb, e_out, lp); diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index a73cb390a35..c5ab4ca75ed 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -5173,17 +5173,27 @@ tree_function_versioning (tree old_decl, tree new_decl, /* Add local vars. */ add_local_variables (DECL_STRUCT_FUNCTION (old_decl), cfun, &id, false); - /* Copy the Function's body. */ - copy_body (&id, old_entry_block->count, REG_BR_PROB_BASE, - ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, blocks_to_copy, new_entry); - if (DECL_RESULT (old_decl) != NULL_TREE) { - tree *res_decl = &DECL_RESULT (old_decl); - DECL_RESULT (new_decl) = remap_decl (*res_decl, &id); + tree old_name; + DECL_RESULT (new_decl) = remap_decl (DECL_RESULT (old_decl), &id); lang_hooks.dup_lang_specific_decl (DECL_RESULT (new_decl)); + if (gimple_in_ssa_p (id.src_cfun) + && DECL_BY_REFERENCE (DECL_RESULT (old_decl)) + && (old_name + = gimple_default_def (id.src_cfun, DECL_RESULT (old_decl)))) + { + tree new_name = make_ssa_name (DECL_RESULT (new_decl), NULL); + insert_decl_map (&id, old_name, new_name); + SSA_NAME_DEF_STMT (new_name) = gimple_build_nop (); + set_default_def (DECL_RESULT (new_decl), new_name); + } } + /* Copy the Function's body. */ + copy_body (&id, old_entry_block->count, REG_BR_PROB_BASE, + ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, blocks_to_copy, new_entry); + /* Renumber the lexical scoping (non-code) blocks consecutively. */ number_blocks (new_decl); diff --git a/gcc/xcoffout.c b/gcc/xcoffout.c index 2b29d985334..84b1436fb7d 100644 --- a/gcc/xcoffout.c +++ b/gcc/xcoffout.c @@ -81,8 +81,15 @@ const char *xcoff_lastfile; #define ASM_OUTPUT_LINE(FILE,LINENUM) \ do \ { \ + /* Make sure we're in a function and prevent output of .line 0, as \ + line # 0 is meant for symbol addresses in xcoff. Additionally, \ + line numbers are 'unsigned short' in 32-bit mode. */ \ if (xcoff_begin_function_line >= 0) \ - fprintf (FILE, "\t.line\t%d\n", ABS_OR_RELATIVE_LINENO (LINENUM)); \ + { \ + int lno = ABS_OR_RELATIVE_LINENO (LINENUM); \ + if (lno > 0 && (TARGET_64BIT || lno <= (int)USHRT_MAX)) \ + fprintf (FILE, "\t.line\t%d\n", lno); \ + } \ } \ while (0) |