diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2015-01-16 19:05:07 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2015-01-16 19:05:07 +0000 |
commit | dd8982995c957bd6664abba15e9b846ad89f1837 (patch) | |
tree | 5906c6e4172e382866e8aa21071b2ee78f9377ef | |
parent | 38b3ff4afb12b031ebed05d98d8427fd429dc579 (diff) | |
parent | 77688d70590330ad4b56d6fb690456d72406c6a2 (diff) | |
download | gcc-dd8982995c957bd6664abba15e9b846ad89f1837.zip gcc-dd8982995c957bd6664abba15e9b846ad89f1837.tar.gz gcc-dd8982995c957bd6664abba15e9b846ad89f1837.tar.bz2 |
Merge from trunk revision 219753.
From-SVN: r219769
96 files changed, 3446 insertions, 217 deletions
@@ -1,3 +1,7 @@ +2015-01-15 Martin Uecker <uecker@eecs.berkeley.edu> + + * MAINTAINERS: (Write After Approval): Add myself. + 2015-01-15 Philipp Tomsich <ptomsich@theobroma-systems.com> * MAINTAINERS: (Write After Approval): Add myself. diff --git a/MAINTAINERS b/MAINTAINERS index efa87bd..d6e8284 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -576,6 +576,7 @@ Ilya Tocar <tocarip@gmail.com> Philipp Tomsich <philipp.tomsich@theobroma-systems.com> Konrad Trifunovic <konrad.trifunovic@inria.fr> Markus Trippelsdorf <markus@trippelsdorf.de> +Martin Uecker <uecker@eecs.berkeley.edu> David Ung <davidu@mips.com> Neil Vachharajani <nvachhar@gmail.com> Kris Van Hees <kris.van.hees@oracle.com> diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 62735a7..55e0315 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,204 @@ +2015-01-16 Segher Boessenkool <segher@kernel.crashing.org> + + * config/rs6000/rs6000.c (TARGET_LIBGCC_CMP_RETURN_MODE, + TARGET_LIBGCC_SHIFT_COUNT_MODE, TARGET_UNWIND_WORD_MODE): Implement + as ... + (rs6000_abi_word_mode): New function. + +2015-01-16 Segher Boessenkool <segher@kernel.crashing.org> + + * config/rs6000/rs6000.c (rs6000_va_start): Use MIN_UNITS_PER_WORD + instead of UNITS_PER_WORD to describe the size of stack slots. + +2015-01-16 Segher Boessenkool <segher@kernel.crashing.org> + + * config/rs6000/rs6000.c (TARGET_PROMOTE_FUNCTION_MODE): Implement + as rs6000_promote_function_mode. Move comment to there. + (rs6000_promote_function_mode): New function. + +2015-01-16 Segher Boessenkool <segher@kernel.crashing.org> + + * config/rs6000/rs6000.h (PROMOTE_MODE): Correct test for when -m32 + -mpowerpc64 is active. + +2015-01-16 Ilya Enkovich <ilya.enkovich@intel.com> + + PR middle-end/64353 + * tree-cfg.c (pass_data_fixup_cfg): Update SSA for + virtuals on start. + +2015-01-16 James Greenhalgh <james.greenhalgh@arm.com> + + * config/arm/cortex-a57.md: Remove duplicate of file accidentally + introduced in revision 219724. + +2015-01-16 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + Ramana Radhakrishnan <ramana.radhakrishnan@arm.com> + + PR target/64263 + * config/aarch64/aarch64.md (*movsi_aarch64): Don't split if the + destination is not a GP reg. + (*movdi_aarch64): Likewise. + +2015-01-16 David Edelsohn <dje.gcc@gmail.com> + + PR target/64623 + * config/rs6000/default64.h: Revert ISA change. + +2015-01-16 Richard Biener <rguenther@suse.de> + + PR middle-end/64614 + * tree-ssa-uninit.c: Include tree-cfg.h. + (MAX_SWITCH_CASES): New define. + (convert_control_dep_chain_into_preds): Handle switch statements. + (is_pred_expr_subset_of): Handle x == CST vs. (x & CST) != 0. + (normalize_one_pred_1): Do not split bit-manipulations. + Record (x & CST). + +2015-01-16 Richard Biener <rguenther@suse.de> + + PR tree-optimization/64568 + * tree-ssa-forwprop.c (pass_forwprop::execute): Guard + complex load rewriting for TARGET_MEM_REFs. + +2015-01-16 Uros Bizjak <ubizjak@gmail.com> + + * builtins.c (expand_builtin_acc_on_device): Check target for NULL. + +2015-01-16 Matthew Wahab <matthew.wahab@arm.com> + + PR target/64149 + * config/aarch64/aarch64.opt: Remove lra option and aarch64_lra_flag + variable. + * config/aarch64/aarch64.c (TARGET_LRA_P): Set to hook_bool_void_true. + (aarch64_lra_p): Remove. + +2015-01-16 Ilya Enkovich <ilya.enkovich@intel.com> + + PR target/64363 + * ipa-chkp.h (chkp_instrumentable_p): New. + * ipa-chkp.c: Include tree-inline.h. + (chkp_instrumentable_p): New. + (chkp_maybe_create_clone): Use chkp_instrumentable_p. + Fix processing of not instrumentable functions. + (chkp_versioning): Use chkp_instrumentable_p. Warn about + not instrumentable functions. + * tree-chkp.c (chkp_add_bounds_to_call_stmt): Use + chkp_instrumentable_p. + * tree-inline.h (copy_forbidden): New. + * tree-inline.c (copy_forbidden): Not static anymore. + +2015-01-16 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * optc-save-gen.awk (cl_target_option_print_diff): Mark indent, + ptr1, ptr2 unused. + +2015-01-16 Robert Suchanek <robert.suchanek@imgtec.com> + + * lra-constraints.c (curr_insn_transform): Change a reload pseudo of + type OP_OUT to OP_INOUT. + +2015-01-16 Robert Suchanek <robert.suchanek@imgtec.com> + + * simplify-rtx.c (simplify_replace_fn_rtx): Simplify (lo_sum + (high x) y) to y if x and y have the same base. + +2015-01-16 James Greenhalgh <james.greenhalgh@arm.com> + + * config/arm/cortex-a57.md: New. + * config/aarch64/aarch64.md: Include it. + * config/aarch64/aarch64-cores.def (cortex-a57): Tune for it. + * config/aarch64/aarch64-tune.md: Regenerate. + +2015-01-16 Zhenqiang Chen <zhenqiang.chen@arm.com> + + PR target/64015 + * ccmp.c (expand_ccmp_next): New function. + (expand_ccmp_expr_1, expand_ccmp_expr): Handle operand insn sequence + and compare insn sequence. + * config/aarch64/aarch64.c (aarch64_code_to_ccmode, + aarch64_gen_ccmp_first, aarch64_gen_ccmp_next): New functions. + (TARGET_GEN_CCMP_FIRST, TARGET_GEN_CCMP_NEXT): New MICRO. + * config/aarch64/aarch64.md (*ccmp_and): Changed to ccmp_and<mode>. + (*ccmp_ior): Changed to ccmp_ior<mode>. + (cmp<mode>): New pattern. + * doc/tm.texi (TARGET_GEN_CCMP_FIRST, TARGET_GEN_CCMP_NEXT): Update + parameters. + * target.def (gen_ccmp_first, gen_ccmp_next): Update parameters. + +2015-01-16 Ilya Tocar <ilya.tocar@intel.com> + + * config/i386/avx2intrin.h (_mm256_bslli_epi128, + _mm256_bsrli_epi128): New. + * config/i386/emmintrin.h (_mm_bsrli_si128, _mm_bslli_si128): Ditto. + +2015-01-15 Jiong Wang <jiong.wang@arm.com> + + * expmed.c (store_bit_field_using_insv): Improve warning message. + Use %wu instead of HOST_WIDE_INT_PRINT_UNSIGNED. + +2015-01-15 Jiong Wang <jiong.wang@arm.com> + + PR rtl-optimization/64011 + * expmed.c (store_bit_field_using_insv): Warn and truncate bitsize when + there is partial overflow. + +2015-01-16 Chung-Ju Wu <jasonwucj@gmail.com> + + * config/nds32/nds32-protos.h (nds32_expand_epilogue): Change + prototype. + (nds32_expand_epilogue_v3pop): Likewise. + * config/nds32/nds32.md (sibcall): Define this for sibling call + optimization. + (sibcall_register): Likewise. + (sibcall_immediate): Likewise. + (sibcall_value): Likewise. + (sibcall_value_register): Likewise. + (sibcall_value_immediate): Likewise. + (sibcall_epilogue): Likewise. + (epilogue): Pass false to indicate this is not a sibcall epilogue. + * config/nds32/nds32.c (nds32_expand_epilogue): Consider sibcall case. + (nds32_expand_epilogue_v3pop): Likewise. + +2015-01-16 Chung-Ju Wu <jasonwucj@gmail.com> + + * config/nds32/nds32-protos.h (nds32_can_use_return_insn): New. + * config/nds32/nds32.md (unspec_volatile_func_return): Remove. + (return_internal): New. + (return): Define this named pattern. + (simple_return): Define this named pattern. + * config/nds32/nds32.c (nds32_expand_epilogue): Emit return_internal + pattern instead of unspec_volatile_func_return. + (nds32_expand_epilogue_v3pop): Likewise. + (nds32_can_use_return_insn): New function. + +2015-01-16 Chung-Ju Wu <jasonwucj@gmail.com> + + * config/nds32/constants.md (UNSPEC_VOLATILE_POP25_RETURN): New. + * config/nds32/nds32.md (pop25return): New. + * config/nds32/nds32.c (nds32_expand_epilogue_v3pop): Emit + pop25return pattern. + +2015-01-16 Chung-Ju Wu <jasonwucj@gmail.com> + + * doc/invoke.texi (NDS32 Options): Remove -mforce-fp-as-gp, + -mforbid-fp-as-gp, and -mex9 options. + +2015-01-16 Chung-Ju Wu <jasonwucj@gmail.com> + + * doc/invoke.texi (NDS32 Options): Add -mcmodel= option and + remove -mgp-direct option. + +2015-01-15 Jan Hubicka <hubicka@ucw.cz> + + * doc/invoke.texi (--param early-inlining-insns): Update default value. + * params.def (PARAM_EARLY_INLINING_INSNS): Set to 14. + +2015-01-15 Jan Hubicka <hubicka@ucw.cz> + + * ipa-inline.c (inline_small_functions): Work around hints + cache issue. + 2015-01-15 Sandra Loosemore <sandra@codesourcery.com> PR target/59710 @@ -276,7 +477,7 @@ cfganal.h, cfgbuild.h, cfgcleanup.h, lcm.h, cfgloopmanip.h, builtins.def, and chkp-builtins.def. -2014-01-15 David Edelsohn <dje.gcc@gmail.com> +2015-01-15 David Edelsohn <dje.gcc@gmail.com> * config/rs6000/default64.h (TARGET_DEFAULT) [LITTLE_ENDIAN]: Use ISA 2.7 (POWER8). @@ -978,7 +1179,7 @@ Do not save lr in case of tail call. * config/arm/thumb2.md (*thumb2_pop_single): New pattern. -2015-01-13 Martin Uecker <uecker@eecs.berkeley.edu> +2015-01-14 Martin Uecker <uecker@eecs.berkeley.edu> * tree-vrp.c (check_array_ref): Emit more warnings for warn_array_bounds >= 2. @@ -1116,7 +1317,7 @@ (perform_symbolic_merge): This. Also fix computation of the range and end of the symbolic number corresponding to the result of a bitwise OR. -2014-01-13 Richard Biener <rguenther@suse.de> +2015-01-13 Richard Biener <rguenther@suse.de> PR tree-optimization/64568 * tree-ssa-forwprop.c (pass_forwprop::execute): Properly diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c index 477e39b..369f65c 100644 --- a/gcc/ada/gcc-interface/utils.c +++ b/gcc/ada/gcc-interface/utils.c @@ -6,7 +6,7 @@ * * * C Implementation File * * * - * Copyright (C) 1992-2014, Free Software Foundation, Inc. * + * Copyright (C) 1992-2015, Free Software Foundation, Inc. * * * * GNAT is free software; you can redistribute it and/or modify it under * * terms of the GNU General Public License as published by the Free Soft- * diff --git a/gcc/builtins.c b/gcc/builtins.c index 9a6a11b..bf5acbc 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -5930,7 +5930,7 @@ expand_builtin_acc_on_device (tree exp, rtx target) v2 = GEN_INT (GOMP_DEVICE_HOST); #endif machine_mode target_mode = TYPE_MODE (integer_type_node); - if (!REG_P (target) || GET_MODE (target) != target_mode) + if (!target || !register_operand (target, target_mode)) target = gen_reg_rtx (target_mode); emit_move_insn (target, const1_rtx); rtx_code_label *done_label = gen_label_rtx (); @@ -92,7 +92,16 @@ along with GCC; see the file COPYING3. If not see * If the final result is not used in a COND_EXPR (checked by function used_in_cond_stmt_p), it calls cstorecc4 pattern to store the CC to a - general register. */ + general register. + + Since the operands of the later compares might clobber CC reg, we do not + emit the insns during expand. We keep the insn sequences in two seq + + * prep_seq, which includes all the insns to prepare the operands. + * gen_seq, which includes all the compare and conditional compares. + + If all checks OK in expand_ccmp_expr, it emits insns in prep_seq, then + insns in gen_seq. */ /* Check whether G is a potential conditional compare candidate. */ static bool @@ -172,6 +181,27 @@ used_in_cond_stmt_p (tree exp) return expand_cond; } +/* PREV is the CC flag from precvious compares. The function expands the + next compare based on G which ops previous compare with CODE. + PREP_SEQ returns all insns to prepare opearands for compare. + GEN_SEQ returnss all compare insns. */ +static rtx +expand_ccmp_next (gimple g, enum tree_code code, rtx prev, + rtx *prep_seq, rtx *gen_seq) +{ + enum rtx_code rcode; + int unsignedp = TYPE_UNSIGNED (TREE_TYPE (gimple_assign_rhs1 (g))); + + gcc_assert (code == BIT_AND_EXPR || code == BIT_IOR_EXPR); + + rcode = get_rtx_code (gimple_assign_rhs_code (g), unsignedp); + + return targetm.gen_ccmp_next (prep_seq, gen_seq, prev, rcode, + gimple_assign_rhs1 (g), + gimple_assign_rhs2 (g), + get_rtx_code (code, 0)); +} + /* Expand conditional compare gimple G. A typical CCMP sequence is like: CC0 = CMP (a, b); @@ -180,9 +210,11 @@ used_in_cond_stmt_p (tree exp) CCn = CCMP (NE (CCn-1, 0), CMP (...)); hook gen_ccmp_first is used to expand the first compare. - hook gen_ccmp_next is used to expand the following CCMP. */ + hook gen_ccmp_next is used to expand the following CCMP. + PREP_SEQ returns all insns to prepare opearand. + GEN_SEQ returns all compare insns. */ static rtx -expand_ccmp_expr_1 (gimple g) +expand_ccmp_expr_1 (gimple g, rtx *prep_seq, rtx *gen_seq) { tree exp = gimple_assign_rhs_to_tree (g); enum tree_code code = TREE_CODE (exp); @@ -199,52 +231,27 @@ expand_ccmp_expr_1 (gimple g) { if (TREE_CODE_CLASS (code1) == tcc_comparison) { - int unsignedp0, unsignedp1; - enum rtx_code rcode0, rcode1; - rtx op0, op1, op2, op3, tmp; + int unsignedp0; + enum rtx_code rcode0; unsignedp0 = TYPE_UNSIGNED (TREE_TYPE (gimple_assign_rhs1 (gs0))); rcode0 = get_rtx_code (code0, unsignedp0); - unsignedp1 = TYPE_UNSIGNED (TREE_TYPE (gimple_assign_rhs1 (gs1))); - rcode1 = get_rtx_code (code1, unsignedp1); - - expand_operands (gimple_assign_rhs1 (gs0), - gimple_assign_rhs2 (gs0), - NULL_RTX, &op0, &op1, EXPAND_NORMAL); - - /* Since the operands of GS1 might clobber CC reg, we expand the - operands of GS1 before GEN_CCMP_FIRST. */ - expand_operands (gimple_assign_rhs1 (gs1), - gimple_assign_rhs2 (gs1), - NULL_RTX, &op2, &op3, EXPAND_NORMAL); - tmp = targetm.gen_ccmp_first (rcode0, op0, op1); + + tmp = targetm.gen_ccmp_first (prep_seq, gen_seq, rcode0, + gimple_assign_rhs1 (gs0), + gimple_assign_rhs2 (gs0)); if (!tmp) return NULL_RTX; - return targetm.gen_ccmp_next (tmp, rcode1, op2, op3, - get_rtx_code (code, 0)); + return expand_ccmp_next (gs1, code, tmp, prep_seq, gen_seq); } else { - rtx op0, op1; - enum rtx_code rcode; - int unsignedp = TYPE_UNSIGNED (TREE_TYPE (gimple_assign_rhs1 (gs0))); - - rcode = get_rtx_code (gimple_assign_rhs_code (gs0), unsignedp); - - /* Hoist the preparation operations above the entire - conditional compare sequence. */ - expand_operands (gimple_assign_rhs1 (gs0), - gimple_assign_rhs2 (gs0), - NULL_RTX, &op0, &op1, EXPAND_NORMAL); - - gcc_assert (code1 == BIT_AND_EXPR || code1 == BIT_IOR_EXPR); + tmp = expand_ccmp_expr_1 (gs1, prep_seq, gen_seq); + if (!tmp) + return NULL_RTX; - /* Note: We swap the order to make the recursive function work. */ - tmp = expand_ccmp_expr_1 (gs1); - if (tmp) - return targetm.gen_ccmp_next (tmp, rcode, op0, op1, - get_rtx_code (code, 0)); + return expand_ccmp_next (gs0, code, tmp, prep_seq, gen_seq); } } else @@ -254,21 +261,11 @@ expand_ccmp_expr_1 (gimple g) if (TREE_CODE_CLASS (gimple_assign_rhs_code (gs1)) == tcc_comparison) { - rtx op0, op1; - enum rtx_code rcode; - int unsignedp = TYPE_UNSIGNED (TREE_TYPE (gimple_assign_rhs1 (gs1))); - - rcode = get_rtx_code (gimple_assign_rhs_code (gs1), unsignedp); - - /* Hoist the preparation operations above the entire - conditional compare sequence. */ - expand_operands (gimple_assign_rhs1 (gs1), - gimple_assign_rhs2 (gs1), - NULL_RTX, &op0, &op1, EXPAND_NORMAL); - tmp = expand_ccmp_expr_1 (gs0); - if (tmp) - return targetm.gen_ccmp_next (tmp, rcode, op0, op1, - get_rtx_code (code, 0)); + tmp = expand_ccmp_expr_1 (gs0, prep_seq, gen_seq); + if (!tmp) + return NULL_RTX; + + return expand_ccmp_next (gs1, code, tmp, prep_seq, gen_seq); } else { @@ -288,23 +285,30 @@ expand_ccmp_expr (gimple g) { rtx_insn *last; rtx tmp; + rtx prep_seq, gen_seq; + + prep_seq = gen_seq = NULL_RTX; if (!ccmp_candidate_p (g)) return NULL_RTX; last = get_last_insn (); - tmp = expand_ccmp_expr_1 (g); + tmp = expand_ccmp_expr_1 (g, &prep_seq, &gen_seq); if (tmp) { enum insn_code icode; enum machine_mode cc_mode = CCmode; - tree lhs = gimple_assign_lhs (g); + /* TMP should be CC. If it is used in a GIMPLE_COND, just return it. Note: Target needs to define "cbranchcc4". */ if (used_in_cond_stmt_p (lhs)) - return tmp; + { + emit_insn (prep_seq); + emit_insn (gen_seq); + return tmp; + } #ifdef SELECT_CC_MODE cc_mode = SELECT_CC_MODE (NE, tmp, const0_rtx); @@ -314,9 +318,12 @@ expand_ccmp_expr (gimple g) icode = optab_handler (cstore_optab, cc_mode); if (icode != CODE_FOR_nothing) { - tree lhs = gimple_assign_lhs (g); enum machine_mode mode = TYPE_MODE (TREE_TYPE (lhs)); rtx target = gen_reg_rtx (mode); + + emit_insn (prep_seq); + emit_insn (gen_seq); + tmp = emit_cstore (target, icode, NE, cc_mode, cc_mode, 0, tmp, const0_rtx, 1, mode); if (tmp) diff --git a/gcc/config/aarch64/aarch64-cores.def b/gcc/config/aarch64/aarch64-cores.def index 35a43e6..f978eb1 100644 --- a/gcc/config/aarch64/aarch64-cores.def +++ b/gcc/config/aarch64/aarch64-cores.def @@ -35,7 +35,7 @@ /* V8 Architecture Processors. */ AARCH64_CORE("cortex-a53", cortexa53, cortexa53, 8, AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC, cortexa53) -AARCH64_CORE("cortex-a57", cortexa15, cortexa15, 8, AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC, cortexa57) +AARCH64_CORE("cortex-a57", cortexa57, cortexa57, 8, AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC, cortexa57) AARCH64_CORE("thunderx", thunderx, thunderx, 8, AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx) AARCH64_CORE("xgene1", xgene1, xgene1, 8, AARCH64_FL_FOR_ARCH8, xgene1) diff --git a/gcc/config/aarch64/aarch64-tune.md b/gcc/config/aarch64/aarch64-tune.md index 6409082..80f59c8 100644 --- a/gcc/config/aarch64/aarch64-tune.md +++ b/gcc/config/aarch64/aarch64-tune.md @@ -1,5 +1,5 @@ ;; -*- buffer-read-only: t -*- ;; Generated automatically by gentune.sh from aarch64-cores.def (define_attr "tune" - "cortexa53,cortexa15,thunderx,xgene1,cortexa57cortexa53" + "cortexa53,cortexa57,thunderx,xgene1,cortexa57cortexa53" (const (symbol_ref "((enum attr_tune) aarch64_tune)"))) diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 34cce91..fdb0116 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -156,7 +156,6 @@ enum aarch64_code_model aarch64_cmodel; #define TARGET_HAVE_TLS 1 #endif -static bool aarch64_lra_p (void); static bool aarch64_composite_type_p (const_tree, machine_mode); static bool aarch64_vfp_is_call_or_return_candidate (machine_mode, const_tree, @@ -7810,13 +7809,6 @@ aapcs_vfp_sub_candidate (const_tree type, machine_mode *modep) return -1; } -/* Return true if we use LRA instead of reload pass. */ -static bool -aarch64_lra_p (void) -{ - return aarch64_lra_flag; -} - /* Return TRUE if the type, as described by TYPE and MODE, is a composite type as described in AAPCS64 \S 4.3. This includes aggregate, union and array types. The C99 floating-point complex types are also considered @@ -10381,6 +10373,198 @@ aarch64_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size, return default_use_by_pieces_infrastructure_p (size, align, op, speed_p); } +static enum machine_mode +aarch64_code_to_ccmode (enum rtx_code code) +{ + switch (code) + { + case NE: + return CC_DNEmode; + + case EQ: + return CC_DEQmode; + + case LE: + return CC_DLEmode; + + case LT: + return CC_DLTmode; + + case GE: + return CC_DGEmode; + + case GT: + return CC_DGTmode; + + case LEU: + return CC_DLEUmode; + + case LTU: + return CC_DLTUmode; + + case GEU: + return CC_DGEUmode; + + case GTU: + return CC_DGTUmode; + + default: + return CCmode; + } +} + +static rtx +aarch64_gen_ccmp_first (rtx *prep_seq, rtx *gen_seq, + int code, tree treeop0, tree treeop1) +{ + enum machine_mode op_mode, cmp_mode, cc_mode; + rtx op0, op1, cmp, target; + int unsignedp = TYPE_UNSIGNED (TREE_TYPE (treeop0)); + enum insn_code icode; + struct expand_operand ops[4]; + + cc_mode = aarch64_code_to_ccmode ((enum rtx_code) code); + if (cc_mode == CCmode) + return NULL_RTX; + + start_sequence (); + expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1, EXPAND_NORMAL); + + op_mode = GET_MODE (op0); + if (op_mode == VOIDmode) + op_mode = GET_MODE (op1); + + switch (op_mode) + { + case QImode: + case HImode: + case SImode: + cmp_mode = SImode; + icode = CODE_FOR_cmpsi; + break; + + case DImode: + cmp_mode = DImode; + icode = CODE_FOR_cmpdi; + break; + + default: + end_sequence (); + return NULL_RTX; + } + + op0 = prepare_operand (icode, op0, 2, op_mode, cmp_mode, unsignedp); + op1 = prepare_operand (icode, op1, 3, op_mode, cmp_mode, unsignedp); + if (!op0 || !op1) + { + end_sequence (); + return NULL_RTX; + } + *prep_seq = get_insns (); + end_sequence (); + + cmp = gen_rtx_fmt_ee ((enum rtx_code) code, cmp_mode, op0, op1); + target = gen_rtx_REG (CCmode, CC_REGNUM); + + create_output_operand (&ops[0], target, CCmode); + create_fixed_operand (&ops[1], cmp); + create_fixed_operand (&ops[2], op0); + create_fixed_operand (&ops[3], op1); + + start_sequence (); + if (!maybe_expand_insn (icode, 4, ops)) + { + end_sequence (); + return NULL_RTX; + } + *gen_seq = get_insns (); + end_sequence (); + + return gen_rtx_REG (cc_mode, CC_REGNUM); +} + +static rtx +aarch64_gen_ccmp_next (rtx *prep_seq, rtx *gen_seq, rtx prev, int cmp_code, + tree treeop0, tree treeop1, int bit_code) +{ + rtx op0, op1, cmp0, cmp1, target; + enum machine_mode op_mode, cmp_mode, cc_mode; + int unsignedp = TYPE_UNSIGNED (TREE_TYPE (treeop0)); + enum insn_code icode = CODE_FOR_ccmp_andsi; + struct expand_operand ops[6]; + + cc_mode = aarch64_code_to_ccmode ((enum rtx_code) cmp_code); + if (cc_mode == CCmode) + return NULL_RTX; + + push_to_sequence ((rtx_insn*) *prep_seq); + expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1, EXPAND_NORMAL); + + op_mode = GET_MODE (op0); + if (op_mode == VOIDmode) + op_mode = GET_MODE (op1); + + switch (op_mode) + { + case QImode: + case HImode: + case SImode: + cmp_mode = SImode; + icode = (enum rtx_code) bit_code == AND ? CODE_FOR_ccmp_andsi + : CODE_FOR_ccmp_iorsi; + break; + + case DImode: + cmp_mode = DImode; + icode = (enum rtx_code) bit_code == AND ? CODE_FOR_ccmp_anddi + : CODE_FOR_ccmp_iordi; + break; + + default: + end_sequence (); + return NULL_RTX; + } + + op0 = prepare_operand (icode, op0, 2, op_mode, cmp_mode, unsignedp); + op1 = prepare_operand (icode, op1, 3, op_mode, cmp_mode, unsignedp); + if (!op0 || !op1) + { + end_sequence (); + return NULL_RTX; + } + *prep_seq = get_insns (); + end_sequence (); + + target = gen_rtx_REG (cc_mode, CC_REGNUM); + cmp1 = gen_rtx_fmt_ee ((enum rtx_code) cmp_code, cmp_mode, op0, op1); + cmp0 = gen_rtx_fmt_ee (NE, cmp_mode, prev, const0_rtx); + + create_fixed_operand (&ops[0], prev); + create_fixed_operand (&ops[1], target); + create_fixed_operand (&ops[2], op0); + create_fixed_operand (&ops[3], op1); + create_fixed_operand (&ops[4], cmp0); + create_fixed_operand (&ops[5], cmp1); + + push_to_sequence ((rtx_insn*) *gen_seq); + if (!maybe_expand_insn (icode, 6, ops)) + { + end_sequence (); + return NULL_RTX; + } + + *gen_seq = get_insns (); + end_sequence (); + + return target; +} + +#undef TARGET_GEN_CCMP_FIRST +#define TARGET_GEN_CCMP_FIRST aarch64_gen_ccmp_first + +#undef TARGET_GEN_CCMP_NEXT +#define TARGET_GEN_CCMP_NEXT aarch64_gen_ccmp_next + /* Implement TARGET_SCHED_MACRO_FUSION_P. Return true if target supports instruction fusion of some sort. */ @@ -11140,7 +11324,7 @@ aarch64_gen_adjusted_ldpstp (rtx *operands, bool load, #define TARGET_LIBGCC_CMP_RETURN_MODE aarch64_libgcc_cmp_return_mode #undef TARGET_LRA_P -#define TARGET_LRA_P aarch64_lra_p +#define TARGET_LRA_P hook_bool_void_true #undef TARGET_MANGLE_TYPE #define TARGET_MANGLE_TYPE aarch64_mangle_type diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index adfa46d..fde5e4f 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -188,7 +188,7 @@ ;; Scheduling (include "../arm/cortex-a53.md") -(include "../arm/cortex-a15.md") +(include "../arm/cortex-a57.md") (include "thunderx.md") (include "../arm/xgene1.md") @@ -248,7 +248,7 @@ "" "") -(define_insn "*ccmp_and" +(define_insn "ccmp_and<mode>" [(set (match_operand 1 "ccmp_cc_register" "") (compare (and:SI @@ -267,7 +267,7 @@ [(set_attr "type" "alus_sreg,alus_imm,alus_imm")] ) -(define_insn "*ccmp_ior" +(define_insn "ccmp_ior<mode>" [(set (match_operand 1 "ccmp_cc_register" "") (compare (ior:SI @@ -286,6 +286,20 @@ [(set_attr "type" "alus_sreg,alus_imm,alus_imm")] ) +(define_expand "cmp<mode>" + [(set (match_operand 0 "cc_register" "") + (match_operator:CC 1 "aarch64_comparison_operator" + [(match_operand:GPI 2 "register_operand" "") + (match_operand:GPI 3 "aarch64_plus_operand" "")]))] + "" + { + operands[1] = gen_rtx_fmt_ee (COMPARE, + SELECT_CC_MODE (GET_CODE (operands[1]), + operands[2], operands[3]), + operands[2], operands[3]); + } +) + (define_insn "*condjump" [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator" [(match_operand 1 "cc_register" "") (const_int 0)]) @@ -845,7 +859,8 @@ fmov\\t%s0, %w1 fmov\\t%w0, %s1 fmov\\t%s0, %s1" - "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode)" + "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode) + && GP_REGNUM_P (REGNO (operands[0]))" [(const_int 0)] "{ aarch64_expand_mov_immediate (operands[0], operands[1]); @@ -877,7 +892,8 @@ fmov\\t%x0, %d1 fmov\\t%d0, %d1 movi\\t%d0, %1" - "(CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), DImode))" + "(CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), DImode)) + && GP_REGNUM_P (REGNO (operands[0]))" [(const_int 0)] "{ aarch64_expand_mov_immediate (operands[0], operands[1]); diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt index 44c6350..f2ef124 100644 --- a/gcc/config/aarch64/aarch64.opt +++ b/gcc/config/aarch64/aarch64.opt @@ -107,10 +107,6 @@ mabi= Target RejectNegative Joined Enum(aarch64_abi) Var(aarch64_abi) Init(AARCH64_ABI_DEFAULT) -mabi=ABI Generate code that conforms to the specified ABI -mlra -Target Report Var(aarch64_lra_flag) Init(1) Save -Use LRA instead of reload (transitional) - Enum Name(aarch64_abi) Type(int) Known AArch64 ABIs (for use with the -mabi= option): diff --git a/gcc/config/arm/cortex-a57.md b/gcc/config/arm/cortex-a57.md new file mode 100644 index 0000000..c9782f2 --- /dev/null +++ b/gcc/config/arm/cortex-a57.md @@ -0,0 +1,797 @@ +;; ARM Cortex-A57 pipeline description +;; Copyright (C) 2014-2015 Free Software Foundation, Inc. +;; +;; This file is part of GCC. +;; +;; GCC is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; GCC is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GCC; see the file COPYING3. If not see +;; <http://www.gnu.org/licenses/>. + +(define_automaton "cortex_a57") + +(define_attr "cortex_a57_neon_type" + "neon_abd, neon_abd_q, neon_arith_acc, neon_arith_acc_q, + neon_arith_basic, neon_arith_complex, + neon_reduc_add_acc, neon_multiply, neon_multiply_q, + neon_multiply_long, neon_mla, neon_mla_q, neon_mla_long, + neon_sat_mla_long, neon_shift_acc, neon_shift_imm_basic, + neon_shift_imm_complex, + neon_shift_reg_basic, neon_shift_reg_basic_q, neon_shift_reg_complex, + neon_shift_reg_complex_q, neon_fp_negabs, neon_fp_arith, + neon_fp_arith_q, neon_fp_reductions_q, neon_fp_cvt_int, + neon_fp_cvt_int_q, neon_fp_cvt16, neon_fp_minmax, neon_fp_mul, + neon_fp_mul_q, neon_fp_mla, neon_fp_mla_q, neon_fp_recpe_rsqrte, + neon_fp_recpe_rsqrte_q, neon_fp_recps_rsqrts, neon_fp_recps_rsqrts_q, + neon_bitops, neon_bitops_q, neon_from_gp, + neon_from_gp_q, neon_move, neon_tbl3_tbl4, neon_zip_q, neon_to_gp, + neon_load_a, neon_load_b, neon_load_c, neon_load_d, neon_load_e, + neon_load_f, neon_store_a, neon_store_b, neon_store_complex, + unknown" + (cond [ + (eq_attr "type" "neon_abd, neon_abd_long") + (const_string "neon_abd") + (eq_attr "type" "neon_abd_q") + (const_string "neon_abd_q") + (eq_attr "type" "neon_arith_acc, neon_reduc_add_acc,\ + neon_reduc_add_acc_q") + (const_string "neon_arith_acc") + (eq_attr "type" "neon_arith_acc_q") + (const_string "neon_arith_acc_q") + (eq_attr "type" "neon_add, neon_add_q, neon_add_long,\ + neon_add_widen, neon_neg, neon_neg_q,\ + neon_reduc_add, neon_reduc_add_q,\ + neon_reduc_add_long, neon_sub, neon_sub_q,\ + neon_sub_long, neon_sub_widen, neon_logic,\ + neon_logic_q, neon_tst, neon_tst_q") + (const_string "neon_arith_basic") + (eq_attr "type" "neon_abs, neon_abs_q, neon_add_halve_narrow_q,\ + neon_add_halve, neon_add_halve_q,\ + neon_sub_halve, neon_sub_halve_q, neon_qabs,\ + neon_qabs_q, neon_qadd, neon_qadd_q, neon_qneg,\ + neon_qneg_q, neon_qsub, neon_qsub_q,\ + neon_sub_halve_narrow_q,\ + neon_compare, neon_compare_q,\ + neon_compare_zero, neon_compare_zero_q,\ + neon_minmax, neon_minmax_q, neon_reduc_minmax,\ + neon_reduc_minmax_q") + (const_string "neon_arith_complex") + + (eq_attr "type" "neon_mul_b, neon_mul_h, neon_mul_s,\ + neon_mul_h_scalar, neon_mul_s_scalar,\ + neon_sat_mul_b, neon_sat_mul_h,\ + neon_sat_mul_s, neon_sat_mul_h_scalar,\ + neon_sat_mul_s_scalar,\ + neon_mul_b_long, neon_mul_h_long,\ + neon_mul_s_long, neon_mul_d_long,\ + neon_mul_h_scalar_long, neon_mul_s_scalar_long,\ + neon_sat_mul_b_long, neon_sat_mul_h_long,\ + neon_sat_mul_s_long, neon_sat_mul_h_scalar_long,\ + neon_sat_mul_s_scalar_long") + (const_string "neon_multiply") + (eq_attr "type" "neon_mul_b_q, neon_mul_h_q, neon_mul_s_q,\ + neon_mul_h_scalar_q, neon_mul_s_scalar_q,\ + neon_sat_mul_b_q, neon_sat_mul_h_q,\ + neon_sat_mul_s_q, neon_sat_mul_h_scalar_q,\ + neon_sat_mul_s_scalar_q") + (const_string "neon_multiply_q") + (eq_attr "type" "neon_mla_b, neon_mla_h, neon_mla_s,\ + neon_mla_h_scalar, neon_mla_s_scalar,\ + neon_mla_b_long, neon_mla_h_long,\ + neon_mla_s_long,\ + neon_mla_h_scalar_long, neon_mla_s_scalar_long") + (const_string "neon_mla") + (eq_attr "type" "neon_mla_b_q, neon_mla_h_q, neon_mla_s_q,\ + neon_mla_h_scalar_q, neon_mla_s_scalar_q") + (const_string "neon_mla_q") + (eq_attr "type" "neon_sat_mla_b_long, neon_sat_mla_h_long,\ + neon_sat_mla_s_long, neon_sat_mla_h_scalar_long,\ + neon_sat_mla_s_scalar_long") + (const_string "neon_sat_mla_long") + + (eq_attr "type" "neon_shift_acc, neon_shift_acc_q") + (const_string "neon_shift_acc") + (eq_attr "type" "neon_shift_imm, neon_shift_imm_q,\ + neon_shift_imm_narrow_q, neon_shift_imm_long") + (const_string "neon_shift_imm_basic") + (eq_attr "type" "neon_sat_shift_imm, neon_sat_shift_imm_q,\ + neon_sat_shift_imm_narrow_q") + (const_string "neon_shift_imm_complex") + (eq_attr "type" "neon_shift_reg") + (const_string "neon_shift_reg_basic") + (eq_attr "type" "neon_shift_reg_q") + (const_string "neon_shift_reg_basic_q") + (eq_attr "type" "neon_sat_shift_reg") + (const_string "neon_shift_reg_complex") + (eq_attr "type" "neon_sat_shift_reg_q") + (const_string "neon_shift_reg_complex_q") + + (eq_attr "type" "neon_fp_neg_s, neon_fp_neg_s_q,\ + neon_fp_abs_s, neon_fp_abs_s_q,\ + neon_fp_neg_d, neon_fp_neg_d_q,\ + neon_fp_abs_d, neon_fp_abs_d_q") + (const_string "neon_fp_negabs") + (eq_attr "type" "neon_fp_addsub_s, neon_fp_abd_s,\ + neon_fp_reduc_add_s, neon_fp_compare_s,\ + neon_fp_minmax_s, neon_fp_round_s,\ + neon_fp_addsub_d, neon_fp_abd_d,\ + neon_fp_reduc_add_d, neon_fp_compare_d,\ + neon_fp_minmax_d, neon_fp_round_d,\ + neon_fp_reduc_minmax_s, neon_fp_reduc_minmax_d") + (const_string "neon_fp_arith") + (eq_attr "type" "neon_fp_addsub_s_q, neon_fp_abd_s_q,\ + neon_fp_reduc_add_s_q, neon_fp_compare_s_q,\ + neon_fp_minmax_s_q, neon_fp_round_s_q,\ + neon_fp_addsub_d_q, neon_fp_abd_d_q,\ + neon_fp_reduc_add_d_q, neon_fp_compare_d_q,\ + neon_fp_minmax_d_q, neon_fp_round_d_q") + (const_string "neon_fp_arith_q") + (eq_attr "type" "neon_fp_reduc_minmax_s_q,\ + neon_fp_reduc_minmax_d_q,\ + neon_fp_reduc_add_s_q, neon_fp_reduc_add_d_q") + (const_string "neon_fp_reductions_q") + (eq_attr "type" "neon_fp_to_int_s, neon_int_to_fp_s,\ + neon_fp_to_int_d, neon_int_to_fp_d") + (const_string "neon_fp_cvt_int") + (eq_attr "type" "neon_fp_to_int_s_q, neon_int_to_fp_s_q,\ + neon_fp_to_int_d_q, neon_int_to_fp_d_q") + (const_string "neon_fp_cvt_int_q") + (eq_attr "type" "neon_fp_cvt_narrow_s_q, neon_fp_cvt_widen_h") + (const_string "neon_fp_cvt16") + (eq_attr "type" "neon_fp_mul_s, neon_fp_mul_s_scalar,\ + neon_fp_mul_d") + (const_string "neon_fp_mul") + (eq_attr "type" "neon_fp_mul_s_q, neon_fp_mul_s_scalar_q,\ + neon_fp_mul_d_q, neon_fp_mul_d_scalar_q") + (const_string "neon_fp_mul_q") + (eq_attr "type" "neon_fp_mla_s, neon_fp_mla_s_scalar,\ + neon_fp_mla_d") + (const_string "neon_fp_mla") + (eq_attr "type" "neon_fp_mla_s_q, neon_fp_mla_s_scalar_q, + neon_fp_mla_d_q, neon_fp_mla_d_scalar_q") + (const_string "neon_fp_mla_q") + (eq_attr "type" "neon_fp_recpe_s, neon_fp_rsqrte_s,\ + neon_fp_recpx_s,\ + neon_fp_recpe_d, neon_fp_rsqrte_d,\ + neon_fp_recpx_d") + (const_string "neon_fp_recpe_rsqrte") + (eq_attr "type" "neon_fp_recpe_s_q, neon_fp_rsqrte_s_q,\ + neon_fp_recpx_s_q,\ + neon_fp_recpe_d_q, neon_fp_rsqrte_d_q,\ + neon_fp_recpx_d_q") + (const_string "neon_fp_recpe_rsqrte_q") + (eq_attr "type" "neon_fp_recps_s, neon_fp_rsqrts_s,\ + neon_fp_recps_d, neon_fp_rsqrts_d") + (const_string "neon_fp_recps_rsqrts") + (eq_attr "type" "neon_fp_recps_s_q, neon_fp_rsqrts_s_q,\ + neon_fp_recps_d_q, neon_fp_rsqrts_d_q") + (const_string "neon_fp_recps_rsqrts_q") + (eq_attr "type" "neon_bsl, neon_cls, neon_cnt,\ + neon_rev, neon_permute, neon_rbit,\ + neon_tbl1, neon_tbl2, neon_zip,\ + neon_dup, neon_dup_q, neon_ext, neon_ext_q,\ + neon_move, neon_move_q, neon_move_narrow_q") + (const_string "neon_bitops") + (eq_attr "type" "neon_bsl_q, neon_cls_q, neon_cnt_q,\ + neon_rev_q, neon_permute_q, neon_rbit_q") + (const_string "neon_bitops_q") + (eq_attr "type" "neon_from_gp,f_mcr,f_mcrr") + (const_string "neon_from_gp") + (eq_attr "type" "neon_from_gp_q") + (const_string "neon_from_gp_q") + (eq_attr "type" "neon_tbl3, neon_tbl4") + (const_string "neon_tbl3_tbl4") + (eq_attr "type" "neon_zip_q") + (const_string "neon_zip_q") + (eq_attr "type" "neon_to_gp, neon_to_gp_q,f_mrc,f_mrrc") + (const_string "neon_to_gp") + + (eq_attr "type" "f_loads, f_loadd,\ + neon_load1_1reg, neon_load1_1reg_q,\ + neon_load1_2reg, neon_load1_2reg_q") + (const_string "neon_load_a") + (eq_attr "type" "neon_load1_3reg, neon_load1_3reg_q,\ + neon_load1_4reg, neon_load1_4reg_q") + (const_string "neon_load_b") + (eq_attr "type" "neon_load1_one_lane, neon_load1_one_lane_q,\ + neon_load1_all_lanes, neon_load1_all_lanes_q,\ + neon_load2_2reg, neon_load2_2reg_q,\ + neon_load2_all_lanes, neon_load2_all_lanes_q") + (const_string "neon_load_c") + (eq_attr "type" "neon_load2_4reg, neon_load2_4reg_q,\ + neon_load3_3reg, neon_load3_3reg_q,\ + neon_load3_one_lane, neon_load3_one_lane_q,\ + neon_load4_4reg, neon_load4_4reg_q") + (const_string "neon_load_d") + (eq_attr "type" "neon_load2_one_lane, neon_load2_one_lane_q,\ + neon_load3_all_lanes, neon_load3_all_lanes_q,\ + neon_load4_all_lanes, neon_load4_all_lanes_q") + (const_string "neon_load_e") + (eq_attr "type" "neon_load4_one_lane, neon_load4_one_lane_q") + (const_string "neon_load_f") + + (eq_attr "type" "f_stores, f_stored,\ + neon_store1_1reg") + (const_string "neon_store_a") + (eq_attr "type" "neon_store1_2reg, neon_store1_1reg_q") + (const_string "neon_store_b") + (eq_attr "type" "neon_store1_3reg, neon_store1_3reg_q,\ + neon_store3_3reg, neon_store3_3reg_q,\ + neon_store2_4reg, neon_store2_4reg_q,\ + neon_store4_4reg, neon_store4_4reg_q,\ + neon_store2_2reg, neon_store2_2reg_q,\ + neon_store3_one_lane, neon_store3_one_lane_q,\ + neon_store4_one_lane, neon_store4_one_lane_q,\ + neon_store1_4reg, neon_store1_4reg_q,\ + neon_store1_one_lane, neon_store1_one_lane_q,\ + neon_store2_one_lane, neon_store2_one_lane_q") + (const_string "neon_store_complex")] + (const_string "unknown"))) + +;; The Cortex-A57 core is modelled as a triple issue pipeline that has +;; the following functional units. +;; 1. Two pipelines for integer operations: SX1, SX2 + +(define_cpu_unit "ca57_sx1_issue" "cortex_a57") +(define_reservation "ca57_sx1" "ca57_sx1_issue") + +(define_cpu_unit "ca57_sx2_issue" "cortex_a57") +(define_reservation "ca57_sx2" "ca57_sx2_issue") + +;; 2. One pipeline for complex integer operations: MX + +(define_cpu_unit "ca57_mx_issue" + "cortex_a57") +(define_reservation "ca57_mx" "ca57_mx_issue") +(define_reservation "ca57_mx_block" "ca57_mx_issue") + +;; 3. Two asymmetric pipelines for Neon and FP operations: CX1, CX2 +(define_automaton "cortex_a57_cx") + +(define_cpu_unit "ca57_cx1_issue" + "cortex_a57_cx") +(define_cpu_unit "ca57_cx2_issue" + "cortex_a57_cx") + +(define_reservation "ca57_cx1" "ca57_cx1_issue") + +(define_reservation "ca57_cx2" "ca57_cx2_issue") +(define_reservation "ca57_cx2_block" "ca57_cx2_issue*2") + +;; 4. One pipeline for branch operations: BX + +(define_cpu_unit "ca57_bx_issue" "cortex_a57") +(define_reservation "ca57_bx" "ca57_bx_issue") + +;; 5. Two pipelines for load and store operations: LS1, LS2. The most +;; valuable thing we can do is force a structural hazard to split +;; up loads/stores. + +(define_cpu_unit "ca57_ls_issue" "cortex_a57") +(define_cpu_unit "ca57_ldr, ca57_str" "cortex_a57") +(define_reservation "ca57_load_model" "ca57_ls_issue,ca57_ldr*2") +(define_reservation "ca57_store_model" "ca57_ls_issue,ca57_str") + +;; Block all issue queues. + +(define_reservation "ca57_block" "ca57_cx1_issue + ca57_cx2_issue + + ca57_mx_issue + ca57_sx1_issue + + ca57_sx2_issue + ca57_ls_issue") + +;; Simple Execution Unit: +;; +;; Simple ALU without shift +(define_insn_reservation "cortex_a57_alu" 2 + (and (eq_attr "tune" "cortexa57") + (eq_attr "type" "alu_imm,alus_imm,logic_imm,logics_imm,\ + alu_sreg,alus_sreg,logic_reg,logics_reg,\ + adc_imm,adcs_imm,adc_reg,adcs_reg,\ + adr,bfm,clz,rbit,rev,alu_dsp_reg,\ + shift_imm,shift_reg,\ + mov_imm,mov_reg,\ + mvn_imm,mvn_reg,\ + mrs,multiple,no_insn")) + "ca57_sx1|ca57_sx2") + +;; ALU ops with immediate shift +(define_insn_reservation "cortex_a57_alu_shift" 3 + (and (eq_attr "tune" "cortexa57") + (eq_attr "type" "extend,\ + alu_shift_imm,alus_shift_imm,\ + crc,logic_shift_imm,logics_shift_imm,\ + mov_shift,mvn_shift")) + "ca57_mx") + +;; Multi-Cycle Execution Unit: +;; +;; ALU ops with register controlled shift +(define_insn_reservation "cortex_a57_alu_shift_reg" 3 + (and (eq_attr "tune" "cortexa57") + (eq_attr "type" "alu_shift_reg,alus_shift_reg,\ + logic_shift_reg,logics_shift_reg,\ + mov_shift_reg,mvn_shift_reg")) + "ca57_mx") + +;; All multiplies +;; TODO: AArch32 and AArch64 have different behaviour +(define_insn_reservation "cortex_a57_mult32" 3 + (and (eq_attr "tune" "cortexa57") + (ior (eq_attr "mul32" "yes") + (eq_attr "mul64" "yes"))) + "ca57_mx") + +;; Integer divide +(define_insn_reservation "cortex_a57_div" 10 + (and (eq_attr "tune" "cortexa57") + (eq_attr "type" "udiv,sdiv")) + "ca57_mx_issue,ca57_mx_block*3") + +;; Block all issue pipes for a cycle +(define_insn_reservation "cortex_a57_block" 1 + (and (eq_attr "tune" "cortexa57") + (eq_attr "type" "block")) + "ca57_block") + +;; Branch execution Unit +;; +;; Branches take one issue slot. +;; No latency as there is no result +(define_insn_reservation "cortex_a57_branch" 0 + (and (eq_attr "tune" "cortexa57") + (eq_attr "type" "branch")) + "ca57_bx") + +;; Load-store execution Unit +;; +;; Loads of up to two words. +(define_insn_reservation "cortex_a57_load1" 5 + (and (eq_attr "tune" "cortexa57") + (eq_attr "type" "load_byte,load1,load2")) + "ca57_load_model") + +;; Loads of three or four words. +(define_insn_reservation "cortex_a57_load3" 5 + (and (eq_attr "tune" "cortexa57") + (eq_attr "type" "load3,load4")) + "ca57_ls_issue*2,ca57_load_model") + +;; Stores of up to two words. +(define_insn_reservation "cortex_a57_store1" 0 + (and (eq_attr "tune" "cortexa57") + (eq_attr "type" "store1,store2")) + "ca57_store_model") + +;; Stores of three or four words. +(define_insn_reservation "cortex_a57_store3" 0 + (and (eq_attr "tune" "cortexa57") + (eq_attr "type" "store3,store4")) + "ca57_ls_issue*2,ca57_store_model") + +;; Advanced SIMD Unit - Integer Arithmetic Instructions. + +(define_insn_reservation "cortex_a57_neon_abd" 5 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_abd")) + "ca57_cx1|ca57_cx2") + +(define_insn_reservation "cortex_a57_neon_abd_q" 5 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_abd_q")) + "ca57_cx1+ca57_cx2") + +(define_insn_reservation "cortex_a57_neon_aba" 7 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_arith_acc")) + "ca57_cx2") + +(define_insn_reservation "cortex_a57_neon_aba_q" 8 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_arith_acc_q")) + "ca57_cx2+(ca57_cx2_issue,ca57_cx2)") + +(define_insn_reservation "cortex_a57_neon_arith_basic" 4 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_arith_basic")) + "ca57_cx1|ca57_cx2") + +(define_insn_reservation "cortex_a57_neon_arith_complex" 5 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_arith_complex")) + "ca57_cx1|ca57_cx2") + +;; Integer Multiply Instructions. + +(define_insn_reservation "cortex_a57_neon_multiply" 6 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_multiply")) + "ca57_cx1") + +(define_insn_reservation "cortex_a57_neon_multiply_q" 7 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_multiply_q")) + "ca57_cx1+(ca57_cx1_issue,ca57_cx1)") + +(define_insn_reservation "cortex_a57_neon_mla" 6 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_mla")) + "ca57_cx1") + +(define_insn_reservation "cortex_a57_neon_mla_q" 7 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_mla_q")) + "ca57_cx1+(ca57_cx1_issue,ca57_cx1)") + +(define_insn_reservation "cortex_a57_neon_sat_mla_long" 6 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_sat_mla_long")) + "ca57_cx1") + +;; Integer Shift Instructions. + +(define_insn_reservation + "cortex_a57_neon_shift_acc" 7 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_shift_acc")) + "ca57_cx2") + +(define_insn_reservation + "cortex_a57_neon_shift_imm_basic" 4 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_shift_imm_basic")) + "ca57_cx2") + +(define_insn_reservation + "cortex_a57_neon_shift_imm_complex" 5 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_shift_imm_complex")) + "ca57_cx2") + +(define_insn_reservation + "cortex_a57_neon_shift_reg_basic" 4 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_shift_reg_basic")) + "ca57_cx2") + +(define_insn_reservation + "cortex_a57_neon_shift_reg_basic_q" 5 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_shift_reg_basic_q")) + "ca57_cx2+(ca57_cx2_issue,ca57_cx2)") + +(define_insn_reservation + "cortex_a57_neon_shift_reg_complex" 5 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_shift_reg_complex")) + "ca57_cx2") + +(define_insn_reservation + "cortex_a57_neon_shift_reg_complex_q" 6 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_shift_reg_complex_q")) + "ca57_cx2+(ca57_cx2_issue,ca57_cx2)") + +;; Floating Point Instructions. + +(define_insn_reservation + "cortex_a57_neon_fp_negabs" 4 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_fp_negabs")) + "(ca57_cx1|ca57_cx2)") + +(define_insn_reservation + "cortex_a57_neon_fp_arith" 6 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_fp_arith")) + "(ca57_cx1|ca57_cx2)") + +(define_insn_reservation + "cortex_a57_neon_fp_arith_q" 6 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_fp_arith_q")) + "(ca57_cx1+ca57_cx2)") + +(define_insn_reservation + "cortex_a57_neon_fp_reductions_q" 10 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_fp_reductions_q")) + "(ca57_cx1+ca57_cx2),(ca57_cx1|ca57_cx2)") + +(define_insn_reservation + "cortex_a57_neon_fp_cvt_int" 6 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_fp_cvt_int")) + "(ca57_cx1|ca57_cx2)") + +(define_insn_reservation + "cortex_a57_neon_fp_cvt_int_q" 6 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_fp_cvt_int_q")) + "(ca57_cx1+ca57_cx2)") + +(define_insn_reservation + "cortex_a57_neon_fp_cvt16" 10 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_fp_cvt16")) + "(ca57_cx1_issue+ca57_cx2_issue),(ca57_cx1|ca57_cx2)") + +(define_insn_reservation + "cortex_a57_neon_fp_mul" 5 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_fp_mul")) + "(ca57_cx1|ca57_cx2)") + +(define_insn_reservation + "cortex_a57_neon_fp_mul_q" 5 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_fp_mul_q")) + "(ca57_cx1+ca57_cx2)") + +(define_insn_reservation + "cortex_a57_neon_fp_mla" 9 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_fp_mla")) + "(ca57_cx1,ca57_cx1)|(ca57_cx2,ca57_cx2)") + +(define_insn_reservation + "cortex_a57_neon_fp_mla_q" 9 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_fp_mla_q")) + "(ca57_cx1+ca57_cx2),(ca57_cx1,ca57_cx2)") + +(define_insn_reservation + "cortex_a57_neon_fp_recpe_rsqrte" 6 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_fp_recpe_rsqrte")) + "(ca57_cx1|ca57_cx2)") + +(define_insn_reservation + "cortex_a57_neon_fp_recpe_rsqrte_q" 6 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_fp_recpe_rsqrte_q")) + "(ca57_cx1+ca57_cx2)") + +(define_insn_reservation + "cortex_a57_neon_fp_recps_rsqrts" 10 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_fp_recps_rsqrts")) + "(ca57_cx1|ca57_cx2)") + +(define_insn_reservation + "cortex_a57_neon_fp_recps_rsqrts_q" 10 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_fp_recps_rsqrts_q")) + "(ca57_cx1+ca57_cx2)") + +;; Miscellaneous Instructions. + +(define_insn_reservation + "cortex_a57_neon_bitops" 4 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_bitops")) + "(ca57_cx1|ca57_cx2)") + +(define_insn_reservation + "cortex_a57_neon_bitops_q" 4 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_bitops_q")) + "(ca57_cx1+ca57_cx2)") + +(define_insn_reservation + "cortex_a57_neon_from_gp" 9 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_from_gp")) + "(ca57_ls_issue+ca57_cx1_issue,ca57_cx1) + |(ca57_ls_issue+ca57_cx2_issue,ca57_cx2)") + +(define_insn_reservation + "cortex_a57_neon_from_gp_q" 9 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_from_gp_q")) + "(ca57_ls_issue+ca57_cx1_issue,ca57_cx1) + +(ca57_ls_issue+ca57_cx2_issue,ca57_cx2)") + +(define_insn_reservation + "cortex_a57_neon_tbl3_tbl4" 7 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_tbl3_tbl4")) + "(ca57_cx1_issue,ca57_cx1) + +(ca57_cx2_issue,ca57_cx2)") + +(define_insn_reservation + "cortex_a57_neon_zip_q" 7 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_zip_q")) + "(ca57_cx1_issue,ca57_cx1) + +(ca57_cx2_issue,ca57_cx2)") + +(define_insn_reservation + "cortex_a57_neon_to_gp" 7 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_to_gp")) + "((ca57_ls_issue+ca57_sx1_issue),ca57_sx1) + |((ca57_ls_issue+ca57_sx2_issue),ca57_sx2)") + +;; Load Instructions. + +(define_insn_reservation + "cortex_a57_neon_load_a" 6 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_load_a")) + "ca57_load_model") + +(define_insn_reservation + "cortex_a57_neon_load_b" 7 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_load_b")) + "ca57_ls_issue,ca57_ls_issue+ca57_ldr,ca57_ldr*2") + +(define_insn_reservation + "cortex_a57_neon_load_c" 9 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_load_c")) + "ca57_load_model+(ca57_cx1|ca57_cx2)") + +(define_insn_reservation + "cortex_a57_neon_load_d" 11 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_load_d")) + "ca57_cx1_issue+ca57_cx2_issue, + ca57_ls_issue+ca57_ls_issue,ca57_ldr*2") + +(define_insn_reservation + "cortex_a57_neon_load_e" 9 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_load_e")) + "ca57_load_model+(ca57_cx1|ca57_cx2)") + +(define_insn_reservation + "cortex_a57_neon_load_f" 11 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_load_f")) + "ca57_cx1_issue+ca57_cx2_issue, + ca57_ls_issue+ca57_ls_issue,ca57_ldr*2") + +;; Store Instructions. + +(define_insn_reservation + "cortex_a57_neon_store_a" 0 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_store_a")) + "ca57_store_model") + +(define_insn_reservation + "cortex_a57_neon_store_b" 0 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_store_b")) + "ca57_store_model") + +;; These block issue for a number of cycles proportional to the number +;; of 64-bit chunks they will store, we don't attempt to model that +;; precisely, treat them as blocking execution for two cycles when +;; issued. +(define_insn_reservation + "cortex_a57_neon_store_complex" 0 + (and (eq_attr "tune" "cortexa57") + (eq_attr "cortex_a57_neon_type" "neon_store_complex")) + "ca57_block*2") + +;; Floating-Point Operations. + +(define_insn_reservation "cortex_a57_fp_const" 4 + (and (eq_attr "tune" "cortexa57") + (eq_attr "type" "fconsts,fconstd")) + "(ca57_cx1|ca57_cx2)") + +(define_insn_reservation "cortex_a57_fp_add_sub" 6 + (and (eq_attr "tune" "cortexa57") + (eq_attr "type" "fadds,faddd")) + "(ca57_cx1|ca57_cx2)") + +(define_insn_reservation "cortex_a57_fp_mul" 6 + (and (eq_attr "tune" "cortexa57") + (eq_attr "type" "fmuls,fmuld")) + "(ca57_cx1|ca57_cx2)") + +(define_insn_reservation "cortex_a57_fp_mac" 10 + (and (eq_attr "tune" "cortexa57") + (eq_attr "type" "fmacs,ffmas,fmacd,ffmad")) + "(ca57_cx1,nothing,nothing,ca57_cx1) \ + |(ca57_cx2,nothing,nothing,ca57_cx2)") + +(define_insn_reservation "cortex_a57_fp_cvt" 6 + (and (eq_attr "tune" "cortexa57") + (eq_attr "type" "f_cvt,f_cvtf2i,f_cvti2f")) + "(ca57_cx1|ca57_cx2)") + +(define_insn_reservation "cortex_a57_fp_cmp" 7 + (and (eq_attr "tune" "cortexa57") + (eq_attr "type" "fcmps,fcmpd")) + "ca57_cx2") + +(define_insn_reservation "cortex_a57_fp_arith" 4 + (and (eq_attr "tune" "cortexa57") + (eq_attr "type" "ffariths,ffarithd")) + "(ca57_cx1|ca57_cx2)") + +(define_insn_reservation "cortex_a57_fp_cpys" 4 + (and (eq_attr "tune" "cortexa57") + (eq_attr "type" "fmov")) + "(ca57_cx1|ca57_cx2)") + +(define_insn_reservation "cortex_a57_fp_divs" 12 + (and (eq_attr "tune" "cortexa57") + (eq_attr "type" "fdivs, fsqrts,\ + neon_fp_div_s, neon_fp_sqrt_s")) + "ca57_cx2_block*5") + +(define_insn_reservation "cortex_a57_fp_divd" 16 + (and (eq_attr "tune" "cortexa57") + (eq_attr "type" "fdivd, fsqrtd, neon_fp_div_d, neon_fp_sqrt_d")) + "ca57_cx2_block*3") + +(define_insn_reservation "cortex_a57_neon_fp_div_q" 20 + (and (eq_attr "tune" "cortexa57") + (eq_attr "type" "fdivd, fsqrtd,\ + neon_fp_div_s_q, neon_fp_div_d_q,\ + neon_fp_sqrt_s_q, neon_fp_sqrt_d_q")) + "ca57_cx2_block*3") + +(define_insn_reservation "cortex_a57_crypto_simple" 4 + (and (eq_attr "tune" "cortexa57") + (eq_attr "type" "crypto_aese,crypto_aesmc,crypto_sha1_fast")) + "ca57_cx2") + +(define_insn_reservation "cortex_a57_crypto_complex" 7 + (and (eq_attr "tune" "cortexa57") + (eq_attr "type" "crypto_sha1_slow")) + "ca57_cx2+(ca57_cx2_issue,ca57_cx2)") + +(define_insn_reservation "cortex_a57_crypto_xor" 7 + (and (eq_attr "tune" "cortexa57") + (eq_attr "type" "crypto_sha1_xor")) + "(ca57_cx1+ca57_cx2)") + +;; We lie with calls. They take up all issue slots, but are otherwise +;; not harmful. +(define_insn_reservation "cortex_a57_call" 1 + (and (eq_attr "tune" "cortexa57") + (eq_attr "type" "call")) + "ca57_sx1_issue+ca57_sx2_issue+ca57_cx1_issue+ca57_cx2_issue\ + +ca57_mx_issue+ca57_bx_issue+ca57_ls_issue" +) + +;; Simple execution unit bypasses +(define_bypass 1 "cortex_a57_alu" + "cortex_a57_alu,cortex_a57_alu_shift,cortex_a57_alu_shift_reg") +(define_bypass 2 "cortex_a57_alu_shift" + "cortex_a57_alu,cortex_a57_alu_shift,cortex_a57_alu_shift_reg") +(define_bypass 2 "cortex_a57_alu_shift_reg" + "cortex_a57_alu,cortex_a57_alu_shift,cortex_a57_alu_shift_reg") +(define_bypass 1 "cortex_a57_alu" "cortex_a57_load1,cortex_a57_load3") +(define_bypass 2 "cortex_a57_alu_shift" "cortex_a57_load1,cortex_a57_load3") +(define_bypass 2 "cortex_a57_alu_shift_reg" + "cortex_a57_load1,cortex_a57_load3") + +;; An MLA or a MUL can feed a dependent MLA. +(define_bypass 5 "cortex_a57_neon_*mla*,cortex_a57_neon_*mul*" + "cortex_a57_neon_*mla*") + +(define_bypass 5 "cortex_a57_fp_mul,cortex_a57_fp_mac" + "cortex_a57_fp_mac") + +;; We don't need to care about control hazards, either the branch is +;; predicted in which case we pay no penalty, or the branch is +;; mispredicted in which case instruction scheduling will be unlikely to +;; help. +(define_bypass 1 "cortex_a57_*" + "cortex_a57_call,cortex_a57_branch") + diff --git a/gcc/config/i386/avx2intrin.h b/gcc/config/i386/avx2intrin.h index 669f1dc..b2a2f48 100644 --- a/gcc/config/i386/avx2intrin.h +++ b/gcc/config/i386/avx2intrin.h @@ -645,11 +645,20 @@ _mm256_sign_epi32 (__m256i __X, __m256i __Y) #ifdef __OPTIMIZE__ extern __inline __m256i __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_bslli_epi128 (__m256i __A, const int __N) +{ + return (__m256i)__builtin_ia32_pslldqi256 (__A, __N * 8); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) _mm256_slli_si256 (__m256i __A, const int __N) { return (__m256i)__builtin_ia32_pslldqi256 (__A, __N * 8); } #else +#define _mm256_bslli_epi128(A, N) \ + ((__m256i)__builtin_ia32_pslldqi256 ((__m256i)(A), (int)(N) * 8)) #define _mm256_slli_si256(A, N) \ ((__m256i)__builtin_ia32_pslldqi256 ((__m256i)(A), (int)(N) * 8)) #endif @@ -727,11 +736,20 @@ _mm256_sra_epi32 (__m256i __A, __m128i __B) #ifdef __OPTIMIZE__ extern __inline __m256i __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_bsrli_epi128 (__m256i __A, const int __N) +{ + return (__m256i)__builtin_ia32_psrldqi256 (__A, __N * 8); +} + +extern __inline __m256i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) _mm256_srli_si256 (__m256i __A, const int __N) { return (__m256i)__builtin_ia32_psrldqi256 (__A, __N * 8); } #else +#define _mm256_bsrli_epi128(A, N) \ + ((__m256i)__builtin_ia32_psrldqi256 ((__m256i)(A), (int)(N) * 8)) #define _mm256_srli_si256(A, N) \ ((__m256i)__builtin_ia32_psrldqi256 ((__m256i)(A), (int)(N) * 8)) #endif diff --git a/gcc/config/i386/emmintrin.h b/gcc/config/i386/emmintrin.h index ad37fac..b19f05a 100644 --- a/gcc/config/i386/emmintrin.h +++ b/gcc/config/i386/emmintrin.h @@ -1165,6 +1165,18 @@ _mm_srai_epi32 (__m128i __A, int __B) #ifdef __OPTIMIZE__ extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_bsrli_si128 (__m128i __A, const int __N) +{ + return (__m128i)__builtin_ia32_psrldqi128 (__A, __N * 8); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_bslli_si128 (__m128i __A, const int __N) +{ + return (__m128i)__builtin_ia32_pslldqi128 (__A, __N * 8); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_srli_si128 (__m128i __A, const int __N) { return (__m128i)__builtin_ia32_psrldqi128 (__A, __N * 8); @@ -1176,6 +1188,10 @@ _mm_slli_si128 (__m128i __A, const int __N) return (__m128i)__builtin_ia32_pslldqi128 (__A, __N * 8); } #else +#define _mm_bsrli_si128(A, N) \ + ((__m128i)__builtin_ia32_psrldqi128 ((__m128i)(A), (int)(N) * 8)) +#define _mm_bslli_si128(A, N) \ + ((__m128i)__builtin_ia32_pslldqi128 ((__m128i)(A), (int)(N) * 8)) #define _mm_srli_si128(A, N) \ ((__m128i)__builtin_ia32_psrldqi128 ((__m128i)(A), (int)(N) * 8)) #define _mm_slli_si128(A, N) \ diff --git a/gcc/config/nds32/constants.md b/gcc/config/nds32/constants.md index 1c37c5f..ea1cd4c 100644 --- a/gcc/config/nds32/constants.md +++ b/gcc/config/nds32/constants.md @@ -41,6 +41,7 @@ UNSPEC_VOLATILE_MTUSR UNSPEC_VOLATILE_SETGIE_EN UNSPEC_VOLATILE_SETGIE_DIS + UNSPEC_VOLATILE_POP25_RETURN ]) ;; ------------------------------------------------------------------------ diff --git a/gcc/config/nds32/nds32-protos.h b/gcc/config/nds32/nds32-protos.h index 328e061..620d897 100644 --- a/gcc/config/nds32/nds32-protos.h +++ b/gcc/config/nds32/nds32-protos.h @@ -58,9 +58,9 @@ extern void nds32_init_cumulative_args (CUMULATIVE_ARGS *, /* -- Function Entry and Exit. */ extern void nds32_expand_prologue (void); -extern void nds32_expand_epilogue (void); +extern void nds32_expand_epilogue (bool); extern void nds32_expand_prologue_v3push (void); -extern void nds32_expand_epilogue_v3pop (void); +extern void nds32_expand_epilogue_v3pop (bool); /* ------------------------------------------------------------------------ */ @@ -120,6 +120,10 @@ extern const char *nds32_output_32bit_load_s (rtx *, int); extern const char *nds32_output_stack_push (rtx); extern const char *nds32_output_stack_pop (rtx); +/* Auxiliary functions to check using return with null epilogue. */ + +extern int nds32_can_use_return_insn (void); + /* Auxiliary functions to decide output alignment or not. */ extern int nds32_target_alignment (rtx); diff --git a/gcc/config/nds32/nds32.c b/gcc/config/nds32/nds32.c index f7d5e70..1845bc2 100644 --- a/gcc/config/nds32/nds32.c +++ b/gcc/config/nds32/nds32.c @@ -3044,7 +3044,7 @@ nds32_expand_prologue (void) /* Function for normal multiple pop epilogue. */ void -nds32_expand_epilogue (void) +nds32_expand_epilogue (bool sibcall_p) { int sp_adjust; int en4_const; @@ -3087,12 +3087,10 @@ nds32_expand_epilogue (void) RTX_FRAME_RELATED_P (sp_adjust_insn) = 1; } - /* Generate return instruction by using - unspec_volatile_func_return pattern. - Make sure this instruction is after gen_blockage(). - NOTE that $lp will become 'live' - after this instruction has been emitted. */ - emit_insn (gen_unspec_volatile_func_return ()); + /* Generate return instruction by using 'return_internal' pattern. + Make sure this instruction is after gen_blockage(). */ + if (!sibcall_p) + emit_jump_insn (gen_return_internal ()); return; } @@ -3196,9 +3194,9 @@ nds32_expand_epilogue (void) RTX_FRAME_RELATED_P (sp_adjust_insn) = 1; } - /* Generate return instruction by using - unspec_volatile_func_return pattern. */ - emit_insn (gen_unspec_volatile_func_return ()); + /* Generate return instruction. */ + if (!sibcall_p) + emit_jump_insn (gen_return_internal ()); } /* Function for v3push prologue. */ @@ -3331,7 +3329,7 @@ nds32_expand_prologue_v3push (void) /* Function for v3pop epilogue. */ void -nds32_expand_epilogue_v3pop (void) +nds32_expand_epilogue_v3pop (bool sibcall_p) { int sp_adjust; @@ -3350,12 +3348,10 @@ nds32_expand_epilogue_v3pop (void) epilogue code fragment BUT 'ret' instruction. */ if (cfun->machine->naked_p) { - /* Generate return instruction by using - unspec_volatile_func_return pattern. - Make sure this instruction is after gen_blockage(). - NOTE that $lp will become 'live' - after this instruction has been emitted. */ - emit_insn (gen_unspec_volatile_func_return ()); + /* Generate return instruction by using 'return_internal' pattern. + Make sure this instruction is after gen_blockage(). */ + if (!sibcall_p) + emit_jump_insn (gen_return_internal ()); return; } @@ -3449,6 +3445,28 @@ nds32_expand_epilogue_v3pop (void) nds32_emit_stack_v3pop (Rb, Re, GEN_INT (14), GEN_INT (0)); } + + /* Generate return instruction. */ + emit_jump_insn (gen_pop25return ()); +} + +/* Return nonzero if this function is known to have a null epilogue. + This allows the optimizer to omit jumps to jumps if no stack + was created. */ +int +nds32_can_use_return_insn (void) +{ + /* Prior to reloading, we can't tell how many registers must be saved. + Thus we can not determine whether this function has null epilogue. */ + if (!reload_completed) + return 0; + + /* If no stack was created, two conditions must be satisfied: + 1. This is a naked function. + So there is no callee-saved, local size, or outgoing size. + 2. This is NOT a variadic function. + So there is no pushing arguement registers into the stack. */ + return (cfun->machine->naked_p && (cfun->machine->va_args_size == 0)); } /* ------------------------------------------------------------------------ */ diff --git a/gcc/config/nds32/nds32.md b/gcc/config/nds32/nds32.md index 8302969..64823a1 100644 --- a/gcc/config/nds32/nds32.md +++ b/gcc/config/nds32/nds32.md @@ -1988,6 +1988,102 @@ create_template: (const_int 4)))]) +;; ---------------------------------------------------------------------------- + +;; The sibcall patterns. + +;; sibcall +;; sibcall_register +;; sibcall_immediate + +(define_expand "sibcall" + [(parallel [(call (match_operand 0 "memory_operand" "") + (const_int 0)) + (clobber (reg:SI TA_REGNUM)) + (return)])] + "" + "" +) + +(define_insn "*sibcall_register" + [(parallel [(call (mem (match_operand:SI 0 "register_operand" "r, r")) + (match_operand 1)) + (clobber (reg:SI TA_REGNUM)) + (return)])] + "" + "@ + jr5\t%0 + jr\t%0" + [(set_attr "type" "branch,branch") + (set_attr "length" " 2, 4")]) + +(define_insn "*sibcall_immediate" + [(parallel [(call (mem (match_operand:SI 0 "immediate_operand" "i")) + (match_operand 1)) + (clobber (reg:SI TA_REGNUM)) + (return)])] + "" +{ + if (TARGET_CMODEL_LARGE) + return "b\t%0"; + else + return "j\t%0"; +} + [(set_attr "type" "branch") + (set (attr "length") + (if_then_else (match_test "TARGET_CMODEL_LARGE") + (const_int 12) + (const_int 4)))]) + +;; sibcall_value +;; sibcall_value_register +;; sibcall_value_immediate + +(define_expand "sibcall_value" + [(parallel [(set (match_operand 0) + (call (match_operand 1 "memory_operand" "") + (const_int 0))) + (clobber (reg:SI TA_REGNUM)) + (return)])] + "" + "" +) + +(define_insn "*sibcall_value_register" + [(parallel [(set (match_operand 0) + (call (mem (match_operand:SI 1 "register_operand" "r, r")) + (match_operand 2))) + (clobber (reg:SI TA_REGNUM)) + (return)])] + "" + "@ + jr5\t%1 + jr\t%1" + [(set_attr "type" "branch,branch") + (set_attr "length" " 2, 4")]) + +(define_insn "*sibcall_value_immediate" + [(parallel [(set (match_operand 0) + (call (mem (match_operand:SI 1 "immediate_operand" "i")) + (match_operand 2))) + (clobber (reg:SI TA_REGNUM)) + (return)])] + "" +{ + if (TARGET_CMODEL_LARGE) + return "b\t%1"; + else + return "j\t%1"; +} + [(set_attr "type" "branch") + (set (attr "length") + (if_then_else (match_test "TARGET_CMODEL_LARGE") + (const_int 12) + (const_int 4)))]) + + +;; ---------------------------------------------------------------------------- + ;; prologue and epilogue. (define_expand "prologue" [(const_int 0)] @@ -2014,9 +2110,23 @@ create_template: if (TARGET_V3PUSH && !nds32_isr_function_p (current_function_decl) && (cfun->machine->va_args_size == 0)) - nds32_expand_epilogue_v3pop (); + nds32_expand_epilogue_v3pop (false); else - nds32_expand_epilogue (); + nds32_expand_epilogue (false); + DONE; +}) + +(define_expand "sibcall_epilogue" [(const_int 0)] + "" +{ + /* Pass true to indicate that this is sibcall epilogue and + exit from a function without the final branch back to the + calling function. */ + if (TARGET_V3PUSH && !nds32_isr_function_p (current_function_decl)) + nds32_expand_epilogue_v3pop (true); + else + nds32_expand_epilogue (true); + DONE; }) @@ -2090,17 +2200,27 @@ create_template: ;; ---------------------------------------------------------------------------- -;; unspec operation patterns +;; Return operation patterns ;; ---------------------------------------------------------------------------- -;; In nds32 target, the 'ret5' instuction is actually 'jr5 $lp'. -;; This pattern is designed to distinguish function return -;; from general indirect_jump pattern so that we can directly -;; generate 'ret5' for readability. +;; Use this pattern to expand a return instruction +;; with simple_return rtx if no epilogue is required. +(define_expand "return" + [(simple_return)] + "nds32_can_use_return_insn ()" + "" +) -(define_insn "unspec_volatile_func_return" - [(set (pc) - (unspec_volatile:SI [(reg:SI LP_REGNUM)] UNSPEC_VOLATILE_FUNC_RETURN))] +;; This pattern is expanded only by the shrink-wrapping optimization +;; on paths where the function prologue has not been executed. +(define_expand "simple_return" + [(simple_return)] + "" + "" +) + +(define_insn "return_internal" + [(simple_return)] "" { if (TARGET_16_BIT) @@ -2108,7 +2228,7 @@ create_template: else return "ret"; } - [(set_attr "type" "misc") + [(set_attr "type" "branch") (set_attr "enabled" "1") (set (attr "length") (if_then_else (match_test "TARGET_16_BIT") @@ -2253,3 +2373,15 @@ create_template: (set_attr "length" "4")]) ;; ---------------------------------------------------------------------------- + +;; Pseudo NOPs + +(define_insn "pop25return" + [(return) + (unspec_volatile:SI [(reg:SI LP_REGNUM)] UNSPEC_VOLATILE_POP25_RETURN)] + "" + "! return for pop 25" + [(set_attr "length" "0")] +) + +;; ---------------------------------------------------------------------------- diff --git a/gcc/config/rs6000/default64.h b/gcc/config/rs6000/default64.h index 7536f96..1e7966e 100644 --- a/gcc/config/rs6000/default64.h +++ b/gcc/config/rs6000/default64.h @@ -20,7 +20,7 @@ along with GCC; see the file COPYING3. If not see #if (TARGET_DEFAULT & MASK_LITTLE_ENDIAN) #undef TARGET_DEFAULT -#define TARGET_DEFAULT (ISA_2_7_MASKS_SERVER | MASK_POWERPC64 | MASK_64BIT | MASK_LITTLE_ENDIAN) +#define TARGET_DEFAULT (MASK_PPC_GFXOPT | MASK_POWERPC64 | MASK_64BIT | MASK_LITTLE_ENDIAN) #else #undef TARGET_DEFAULT #define TARGET_DEFAULT (MASK_PPC_GFXOPT | MASK_POWERPC64 | MASK_64BIT) diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index ca21413..3a46333 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -1511,10 +1511,8 @@ static const struct attribute_spec rs6000_attribute_table[] = #undef TARGET_MEMBER_TYPE_FORCES_BLK #define TARGET_MEMBER_TYPE_FORCES_BLK rs6000_member_type_forces_blk -/* On rs6000, function arguments are promoted, as are function return - values. */ #undef TARGET_PROMOTE_FUNCTION_MODE -#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote +#define TARGET_PROMOTE_FUNCTION_MODE rs6000_promote_function_mode #undef TARGET_RETURN_IN_MEMORY #define TARGET_RETURN_IN_MEMORY rs6000_return_in_memory @@ -1678,6 +1676,13 @@ static const struct attribute_spec rs6000_attribute_table[] = #undef TARGET_ATOMIC_ASSIGN_EXPAND_FENV #define TARGET_ATOMIC_ASSIGN_EXPAND_FENV rs6000_atomic_assign_expand_fenv + +#undef TARGET_LIBGCC_CMP_RETURN_MODE +#define TARGET_LIBGCC_CMP_RETURN_MODE rs6000_abi_word_mode +#undef TARGET_LIBGCC_SHIFT_COUNT_MODE +#define TARGET_LIBGCC_SHIFT_COUNT_MODE rs6000_abi_word_mode +#undef TARGET_UNWIND_WORD_MODE +#define TARGET_UNWIND_WORD_MODE rs6000_abi_word_mode /* Processor table. */ @@ -9308,6 +9313,29 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, } } +/* The mode the ABI uses for a word. This is not the same as word_mode + for -m32 -mpowerpc64. This is used to implement various target hooks. */ + +static machine_mode +rs6000_abi_word_mode (void) +{ + return TARGET_32BIT ? SImode : DImode; +} + +/* On rs6000, function arguments are promoted, as are function return + values. */ + +static machine_mode +rs6000_promote_function_mode (const_tree type ATTRIBUTE_UNUSED, + machine_mode mode, + int *punsignedp ATTRIBUTE_UNUSED, + const_tree, int) +{ + PROMOTE_MODE (mode, *punsignedp, type); + + return mode; +} + /* Return true if TYPE must be passed on the stack and not in registers. */ static bool @@ -11227,7 +11255,7 @@ rs6000_va_start (tree valist, rtx nextarg) /* Find the overflow area. */ t = make_tree (TREE_TYPE (ovf), virtual_incoming_args_rtx); if (words != 0) - t = fold_build_pointer_plus_hwi (t, words * UNITS_PER_WORD); + t = fold_build_pointer_plus_hwi (t, words * MIN_UNITS_PER_WORD); t = build2 (MODIFY_EXPR, TREE_TYPE (ovf), ovf, t); TREE_SIDE_EFFECTS (t) = 1; expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index c55d7ed..ef6bb2f 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -733,7 +733,7 @@ extern unsigned char rs6000_recip_bits[]; #define PROMOTE_MODE(MODE,UNSIGNEDP,TYPE) \ if (GET_MODE_CLASS (MODE) == MODE_INT \ - && GET_MODE_SIZE (MODE) < UNITS_PER_WORD) \ + && GET_MODE_SIZE (MODE) < (TARGET_32BIT ? 4 : 8)) \ (MODE) = TARGET_32BIT ? SImode : DImode; /* Define this if most significant bit is lowest numbered diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 889f3c1..ff5fb7a 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,14 @@ +2015-01-16 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/58614 + * pt.c (unify): When BRACE_ENCLOSED_INITIALIZER_P (arg), handle + TREE_TYPE (elt) == error_mark_node. + +2015-01-15 Jan Hubicka <hubicka@ucw.cz> + + PR tree-optimization/62053 + * tree.c (build_cplus_array_type): Layout type after variants are set. + 2015-01-15 Jakub Jelinek <jakub@redhat.com> * cp-gimplify.c (cp_genericize_r): Call diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 55871e5..bc26530 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -17875,6 +17875,8 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, if (!BRACE_ENCLOSED_INITIALIZER_P (elt)) { tree type = TREE_TYPE (elt); + if (type == error_mark_node) + return unify_invalid (explain_p); /* It should only be possible to get here for a call. */ gcc_assert (elt_strict & UNIFY_ALLOW_OUTER_LEVEL); elt_strict |= maybe_adjust_types_for_deduction diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 80f2ce6..afb57a3 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -881,12 +881,12 @@ build_cplus_array_type (tree elt_type, tree index_type) { t = build_min_array_type (elt_type, index_type); set_array_type_canon (t, elt_type, index_type); - if (!dependent) - layout_type (t); TYPE_MAIN_VARIANT (t) = m; TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m); TYPE_NEXT_VARIANT (m) = t; + if (!dependent) + layout_type (t); } } diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 12368e8e..8a9387b 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -861,12 +861,11 @@ Objective-C and Objective-C++ Dialects}. -mperf-ext -mno-perf-ext @gol -mv3push -mno-v3push @gol -m16bit -mno-16bit @gol --mgp-direct -mno-gp-direct @gol -misr-vector-size=@var{num} @gol -mcache-block-size=@var{num} @gol -march=@var{arch} @gol --mforce-fp-as-gp -mforbid-fp-as-gp @gol --mex9 -mctor-dtor -mrelax} +-mcmodel=@var{code-model} @gol +-mctor-dtor -mrelax} @emph{Nios II Options} @gccoptlist{-G @var{num} -mgpopt=@var{option} -mgpopt -mno-gpopt @gol @@ -19153,14 +19152,6 @@ Generate 16-bit instructions. @opindex mno-16-bit Do not generate 16-bit instructions. -@item -mgp-direct -@opindex mgp-direct -Generate GP base instructions directly. - -@item -mno-gp-direct -@opindex mno-gp-direct -Do no generate GP base instructions directly. - @item -misr-vector-size=@var{num} @opindex misr-vector-size Specify the size of each interrupt vector, which must be 4 or 16. @@ -19174,20 +19165,20 @@ which must be a power of 2 between 4 and 512. @opindex march Specify the name of the target architecture. -@item -mforce-fp-as-gp -@opindex mforce-fp-as-gp -Prevent $fp being allocated during register allocation so that compiler -is able to force performing fp-as-gp optimization. - -@item -mforbid-fp-as-gp -@opindex mforbid-fp-as-gp -Forbid using $fp to access static and global variables. -This option strictly forbids fp-as-gp optimization -regardless of @option{-mforce-fp-as-gp}. - -@item -mex9 -@opindex mex9 -Use special directives to guide linker doing ex9 optimization. +@item -mcmodel=@var{code-model} +@opindex mcmodel +Set the code model to one of +@table @asis +@item @samp{small} +All the data and read-only data segments must be within 512KB addressing space. +The text segment must be within 16MB addressing space. +@item @samp{medium} +The data segment must be within 512KB while the read-only data segment can be +within 4GB addressing space. The text segment should be still within 16MB +addressing space. +@item @samp{large} +All the text and data segments can be within 4GB addressing space. +@end table @item -mctor-dtor @opindex mctor-dtor diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 4e6c947..9c81fdb 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -11259,18 +11259,25 @@ This target hook is required only when the target has several different modes and they have different conditional execution capability, such as ARM. @end deftypefn -@deftypefn {Target Hook} rtx TARGET_GEN_CCMP_FIRST (int @var{code}, rtx @var{op0}, rtx @var{op1}) -This function emits a comparison insn for the first of a sequence of - conditional comparisions. It returns a comparison expression appropriate - for passing to @code{gen_ccmp_next} or @code{cbranch_optab}. @var{code} is +@deftypefn {Target Hook} rtx TARGET_GEN_CCMP_FIRST (rtx *@var{prep_seq}, rtx *@var{gen_seq}, int @var{code}, tree @var{op0}, tree @var{op1}) +This function prepares to emit a comparison insn for the first compare in a + sequence of conditional comparisions. It returns a appropriate @code{CC} + for passing to @code{gen_ccmp_next} or @code{cbranch_optab}. The insns to + prepare the compare are saved in @var{prep_seq} and the compare insns are + saved in @var{gen_seq}. They will be emitted when all the compares in the + the conditional comparision are generated without error. @var{code} is the @code{rtx_code} of the compare for @var{op0} and @var{op1}. @end deftypefn -@deftypefn {Target Hook} rtx TARGET_GEN_CCMP_NEXT (rtx @var{prev}, int @var{cmp_code}, rtx @var{op0}, rtx @var{op1}, int @var{bit_code}) -This function emits a conditional comparison within a sequence of - conditional comparisons. The @var{prev} expression is the result of a - prior call to @code{gen_ccmp_first} or @code{gen_ccmp_next}. It may return - @code{NULL} if the combination of @var{prev} and this comparison is +@deftypefn {Target Hook} rtx TARGET_GEN_CCMP_NEXT (rtx *@var{prep_seq}, rtx *@var{gen_seq}, rtx @var{prev}, int @var{cmp_code}, tree @var{op0}, tree @var{op1}, int @var{bit_code}) +This function prepare to emit a conditional comparison within a sequence of + conditional comparisons. It returns a appropriate @code{CC} for passing to + @code{gen_ccmp_next} or @code{cbranch_optab}. The insns to prepare the + compare are saved in @var{prep_seq} and the compare insns are saved in + @var{gen_seq}. They will be emitted when all the compares in the conditional + comparision are generated without error. The @var{prev} expression is the + result of a prior call to @code{gen_ccmp_first} or @code{gen_ccmp_next}. It + may return @code{NULL} if the combination of @var{prev} and this comparison is not supported, otherwise the result must be appropriate for passing to @code{gen_ccmp_next} or @code{cbranch_optab}. @var{code} is the @code{rtx_code} of the compare for @var{op0} and @var{op1}. @var{bit_code} diff --git a/gcc/expmed.c b/gcc/expmed.c index 480601c..18e62a0 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -557,6 +557,21 @@ store_bit_field_using_insv (const extraction_insn *insv, rtx op0, copy_back = true; } + /* There are similar overflow check at the start of store_bit_field_1, + but that only check the situation where the field lies completely + outside the register, while there do have situation where the field + lies partialy in the register, we need to adjust bitsize for this + partial overflow situation. Without this fix, pr48335-2.c on big-endian + will broken on those arch support bit insert instruction, like arm, aarch64 + etc. */ + if (bitsize + bitnum > unit && bitnum < unit) + { + warning (OPT_Wextra, "write of %wu-bit data outside the bound of " + "destination object, data truncated into %wu-bit", + bitsize, unit - bitnum); + bitsize = unit - bitnum; + } + /* If BITS_BIG_ENDIAN is zero on a BYTES_BIG_ENDIAN machine, we count "backwards" from the size of the unit we are inserting into. Otherwise, we count bits from the most significant on a diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 3fd3cfb..c97de7f 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,9 @@ +2015-01-16 Janus Weil <janus@gcc.gnu.org> + + PR fortran/45290 + * decl.c (match_pointer_init): Error out if resolution of init expr + failed. + 2015-01-15 Tobias Burnus <burnus@net-b.de> * openmp.c (check_symbol_not_pointer, resolve_oacc_data_clauses, diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c index dfb760b..2a200fc 100644 --- a/gcc/fortran/decl.c +++ b/gcc/fortran/decl.c @@ -1780,8 +1780,8 @@ match_pointer_init (gfc_expr **init, int procptr) return MATCH_ERROR; } - if (!procptr) - gfc_resolve_expr (*init); + if (!procptr && !gfc_resolve_expr (*init)) + return MATCH_ERROR; if (!gfc_notify_std (GFC_STD_F2008, "non-NULL pointer " "initialization at %C")) diff --git a/gcc/ipa-chkp.c b/gcc/ipa-chkp.c index 30d511d..8e6612e 100644 --- a/gcc/ipa-chkp.c +++ b/gcc/ipa-chkp.c @@ -50,6 +50,7 @@ along with GCC; see the file COPYING3. If not see #include "lto-streamer.h" #include "cgraph.h" #include "tree-chkp.h" +#include "tree-inline.h" #include "ipa-chkp.h" /* Pointer Bounds Checker has two IPA passes to support code instrumentation. @@ -401,6 +402,18 @@ chkp_maybe_clone_builtin_fndecl (tree fndecl) return clone; } +/* Return 1 if function FNDECL should be instrumented. */ + +bool +chkp_instrumentable_p (tree fndecl) +{ + struct function *fn = DECL_STRUCT_FUNCTION (fndecl); + return (!lookup_attribute ("bnd_legacy", DECL_ATTRIBUTES (fndecl)) + && (!flag_chkp_instrument_marked_only + || lookup_attribute ("bnd_instrument", DECL_ATTRIBUTES (fndecl))) + && (!fn || !copy_forbidden (fn, fndecl))); +} + /* Return clone created for instrumentation of NODE or NULL. */ cgraph_node * @@ -483,10 +496,10 @@ chkp_maybe_create_clone (tree fndecl) { /* If function will not be instrumented, then it's instrumented version is a thunk for the original. */ - if (lookup_attribute ("bnd_legacy", DECL_ATTRIBUTES (fndecl)) - || (flag_chkp_instrument_marked_only - && !lookup_attribute ("bnd_instrument", DECL_ATTRIBUTES (fndecl)))) + if (!chkp_instrumentable_p (fndecl)) { + clone->remove_callees (); + clone->remove_all_references (); clone->thunk.thunk_p = true; clone->thunk.add_pointer_bounds_args = true; clone->create_edge (node, NULL, 0, CGRAPH_FREQ_BASE); @@ -532,7 +545,8 @@ chkp_maybe_create_clone (tree fndecl) /* Clone all thunks. */ for (e = node->callers; e; e = e->next_caller) - if (e->caller->thunk.thunk_p) + if (e->caller->thunk.thunk_p + && !e->caller->thunk.add_pointer_bounds_args) { struct cgraph_node *thunk = chkp_maybe_create_clone (e->caller->decl); @@ -578,6 +592,7 @@ static unsigned int chkp_versioning (void) { struct cgraph_node *node; + const char *reason; bitmap_obstack_initialize (NULL); @@ -587,14 +602,20 @@ chkp_versioning (void) && !node->instrumented_version && !node->alias && !node->thunk.thunk_p - && !lookup_attribute ("bnd_legacy", DECL_ATTRIBUTES (node->decl)) - && (!flag_chkp_instrument_marked_only - || lookup_attribute ("bnd_instrument", - DECL_ATTRIBUTES (node->decl))) && (!DECL_BUILT_IN (node->decl) || (DECL_BUILT_IN_CLASS (node->decl) == BUILT_IN_NORMAL && DECL_FUNCTION_CODE (node->decl) < BEGIN_CHKP_BUILTINS))) - chkp_maybe_create_clone (node->decl); + { + if (chkp_instrumentable_p (node->decl)) + chkp_maybe_create_clone (node->decl); + else if ((reason = copy_forbidden (DECL_STRUCT_FUNCTION (node->decl), + node->decl))) + { + if (warning_at (DECL_SOURCE_LOCATION (node->decl), OPT_Wchkp, + "function cannot be instrumented")) + inform (DECL_SOURCE_LOCATION (node->decl), reason, node->decl); + } + } } /* Mark all aliases and thunks of functions with no instrumented diff --git a/gcc/ipa-chkp.h b/gcc/ipa-chkp.h index b087227..6708fe9 100644 --- a/gcc/ipa-chkp.h +++ b/gcc/ipa-chkp.h @@ -23,5 +23,6 @@ along with GCC; see the file COPYING3. If not see extern tree chkp_copy_function_type_adding_bounds (tree orig_type); extern tree chkp_maybe_clone_builtin_fndecl (tree fndecl); extern cgraph_node *chkp_maybe_create_clone (tree fndecl); +extern bool chkp_instrumentable_p (tree fndecl); #endif /* GCC_IPA_CHKP_H */ diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c index 1a227a2..f270cfa 100644 --- a/gcc/ipa-inline.c +++ b/gcc/ipa-inline.c @@ -1655,7 +1655,18 @@ inline_small_functions (void) reset_edge_growth_cache (edge); gcc_assert (old_size_est == estimate_edge_size (edge)); gcc_assert (old_time_est == estimate_edge_time (edge)); - gcc_assert (old_hints_est == estimate_edge_hints (edge)); + /* FIXME: + + gcc_assert (old_hints_est == estimate_edge_hints (edge)); + + fails with profile feedback because some hints depends on + maybe_hot_edge_p predicate and because callee gets inlined to other + calls, the edge may become cold. + This ought to be fixed by computing relative probabilities + for given invocation but that will be better done once whole + code is converted to sreals. Disable for now and revert to "wrong" + value so enable/disable checking paths agree. */ + edge_growth_cache[edge->uid].hints = old_hints_est + 1; /* When updating the edge costs, we only decrease badness in the keys. Increases of badness are handled lazilly; when we see key with out diff --git a/gcc/jit/ChangeLog b/gcc/jit/ChangeLog index ad5382a..1bd439a 100644 --- a/gcc/jit/ChangeLog +++ b/gcc/jit/ChangeLog @@ -1,3 +1,12 @@ +2015-01-16 Jakub Jelinek <jakub@redhat.com> + + * jit-builtins.h (DEF_FUNCTION_TYPE_VAR_5): Fix spelling of + last argument. + (DEF_FUNCTION_TYPE_VAR_8, DEF_FUNCTION_TYPE_VAR_12): Define and + undef afterwards. + * jit-builtins.c (DEF_FUNCTION_TYPE_VAR_8, DEF_FUNCTION_TYPE_VAR_12): + Likewise. + 2015-01-15 Richard Sandiford <richard.sandiford@arm.com> Update copyright years in docs/. diff --git a/gcc/jit/jit-builtins.c b/gcc/jit/jit-builtins.c index 871f63e..47b0198 100644 --- a/gcc/jit/jit-builtins.c +++ b/gcc/jit/jit-builtins.c @@ -313,6 +313,15 @@ builtins_manager::make_type (enum jit_builtin_type type_id) case ENUM: return make_fn_type (ENUM, RETURN, 1, 4, ARG1, ARG2, ARG3, ARG4); #define DEF_FUNCTION_TYPE_VAR_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \ case ENUM: return make_fn_type (ENUM, RETURN, 1, 5, ARG1, ARG2, ARG3, ARG4, ARG5); +#define DEF_FUNCTION_TYPE_VAR_8(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ + ARG6, ARG7, ARG8) \ + case ENUM: return make_fn_type (ENUM, RETURN, 1, 8, ARG1, ARG2, ARG3, \ + ARG4, ARG5, ARG6, ARG7, ARG8); +#define DEF_FUNCTION_TYPE_VAR_12(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ + ARG6, ARG7, ARG8, ARG9, ARG10, ARG11, ARG12) \ + case ENUM: return make_fn_type (ENUM, RETURN, 1, 12, ARG1, ARG2, ARG3, \ + ARG4, ARG5, ARG6, ARG7, ARG8, ARG9, \ + ARG10, ARG11, ARG12); #define DEF_POINTER_TYPE(ENUM, TYPE) \ case ENUM: return make_ptr_type (ENUM, TYPE); @@ -334,6 +343,8 @@ builtins_manager::make_type (enum jit_builtin_type type_id) #undef DEF_FUNCTION_TYPE_VAR_3 #undef DEF_FUNCTION_TYPE_VAR_4 #undef DEF_FUNCTION_TYPE_VAR_5 +#undef DEF_FUNCTION_TYPE_VAR_8 +#undef DEF_FUNCTION_TYPE_VAR_12 #undef DEF_POINTER_TYPE default: diff --git a/gcc/jit/jit-builtins.h b/gcc/jit/jit-builtins.h index e6a0cd4..9101aaf 100644 --- a/gcc/jit/jit-builtins.h +++ b/gcc/jit/jit-builtins.h @@ -45,7 +45,12 @@ enum jit_builtin_type #define DEF_FUNCTION_TYPE_VAR_2(NAME, RETURN, ARG1, ARG2) NAME, #define DEF_FUNCTION_TYPE_VAR_3(NAME, RETURN, ARG1, ARG2, ARG3) NAME, #define DEF_FUNCTION_TYPE_VAR_4(NAME, RETURN, ARG1, ARG2, ARG3, ARG4) NAME, -#define DEF_FUNCTION_TYPE_VAR_5(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG6) \ +#define DEF_FUNCTION_TYPE_VAR_5(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \ + NAME, +#define DEF_FUNCTION_TYPE_VAR_8(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ + ARG6, ARG7, ARG8) NAME, +#define DEF_FUNCTION_TYPE_VAR_12(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ + ARG6, ARG7, ARG8, ARG9, ARG10, ARG11, ARG12) \ NAME, #define DEF_POINTER_TYPE(NAME, TYPE) NAME, #include "builtin-types.def" @@ -65,6 +70,8 @@ enum jit_builtin_type #undef DEF_FUNCTION_TYPE_VAR_3 #undef DEF_FUNCTION_TYPE_VAR_4 #undef DEF_FUNCTION_TYPE_VAR_5 +#undef DEF_FUNCTION_TYPE_VAR_8 +#undef DEF_FUNCTION_TYPE_VAR_12 #undef DEF_POINTER_TYPE BT_LAST }; /* enum jit_builtin_type */ diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c index f102fe5..6e4be72 100644 --- a/gcc/lra-constraints.c +++ b/gcc/lra-constraints.c @@ -3802,6 +3802,8 @@ curr_insn_transform (bool check_only_p) (ira_class_hard_regs[goal_alt[i]][0], GET_MODE (reg), byte, mode) >= 0))))) { + if (type == OP_OUT) + type = OP_INOUT; loc = &SUBREG_REG (*loc); mode = GET_MODE (*loc); } diff --git a/gcc/optc-save-gen.awk b/gcc/optc-save-gen.awk index add0949..58732c0 100644 --- a/gcc/optc-save-gen.awk +++ b/gcc/optc-save-gen.awk @@ -505,9 +505,9 @@ print ""; print "/* Print different target option variables from structures provided as arguments. */"; print "void"; print "cl_target_option_print_diff (FILE *file,"; -print " int indent,"; -print " struct cl_target_option *ptr1,"; -print " struct cl_target_option *ptr2)"; +print " int indent ATTRIBUTE_UNUSED,"; +print " struct cl_target_option *ptr1 ATTRIBUTE_UNUSED,"; +print " struct cl_target_option *ptr2 ATTRIBUTE_UNUSED)"; print "{"; print " fputs (\"\\n\", file);"; diff --git a/gcc/params.def b/gcc/params.def index cbdc477..3f69ce0 100644 --- a/gcc/params.def +++ b/gcc/params.def @@ -198,7 +198,7 @@ DEFPARAM(PARAM_IPCP_UNIT_GROWTH, DEFPARAM(PARAM_EARLY_INLINING_INSNS, "early-inlining-insns", "Maximal estimated growth of function body caused by early inlining of single call", - 11, 0, 0) + 14, 0, 0) DEFPARAM(PARAM_LARGE_STACK_FRAME, "large-stack-frame", "The size of stack frame to be considered large", diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 4ee63d2..d26267d 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -539,9 +539,15 @@ simplify_replace_fn_rtx (rtx x, const_rtx old_rtx, op0 = simplify_replace_fn_rtx (XEXP (x, 0), old_rtx, fn, data); op1 = simplify_replace_fn_rtx (XEXP (x, 1), old_rtx, fn, data); - /* (lo_sum (high x) x) -> x */ - if (GET_CODE (op0) == HIGH && rtx_equal_p (XEXP (op0, 0), op1)) - return op1; + /* (lo_sum (high x) y) -> y where x and y have the same base. */ + if (GET_CODE (op0) == HIGH) + { + rtx base0, base1, offset0, offset1; + split_const (XEXP (op0, 0), &base0, &offset0); + split_const (op1, &base1, &offset1); + if (rtx_equal_p (base0, base1)) + return op1; + } if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1)) return x; diff --git a/gcc/target.def b/gcc/target.def index 4aebcfe..356f7c1 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -2542,24 +2542,31 @@ modes and they have different conditional execution capability, such as ARM.", DEFHOOK (gen_ccmp_first, - "This function emits a comparison insn for the first of a sequence of\n\ - conditional comparisions. It returns a comparison expression appropriate\n\ - for passing to @code{gen_ccmp_next} or @code{cbranch_optab}. @var{code} is\n\ + "This function prepares to emit a comparison insn for the first compare in a\n\ + sequence of conditional comparisions. It returns a appropriate @code{CC}\n\ + for passing to @code{gen_ccmp_next} or @code{cbranch_optab}. The insns to\n\ + prepare the compare are saved in @var{prep_seq} and the compare insns are\n\ + saved in @var{gen_seq}. They will be emitted when all the compares in the\n\ + the conditional comparision are generated without error. @var{code} is\n\ the @code{rtx_code} of the compare for @var{op0} and @var{op1}.", - rtx, (int code, rtx op0, rtx op1), + rtx, (rtx *prep_seq, rtx *gen_seq, int code, tree op0, tree op1), NULL) DEFHOOK (gen_ccmp_next, - "This function emits a conditional comparison within a sequence of\n\ - conditional comparisons. The @var{prev} expression is the result of a\n\ - prior call to @code{gen_ccmp_first} or @code{gen_ccmp_next}. It may return\n\ - @code{NULL} if the combination of @var{prev} and this comparison is\n\ + "This function prepare to emit a conditional comparison within a sequence of\n\ + conditional comparisons. It returns a appropriate @code{CC} for passing to\n\ + @code{gen_ccmp_next} or @code{cbranch_optab}. The insns to prepare the\n\ + compare are saved in @var{prep_seq} and the compare insns are saved in\n\ + @var{gen_seq}. They will be emitted when all the compares in the conditional\n\ + comparision are generated without error. The @var{prev} expression is the\n\ + result of a prior call to @code{gen_ccmp_first} or @code{gen_ccmp_next}. It\n\ + may return @code{NULL} if the combination of @var{prev} and this comparison is\n\ not supported, otherwise the result must be appropriate for passing to\n\ @code{gen_ccmp_next} or @code{cbranch_optab}. @var{code} is the\n\ @code{rtx_code} of the compare for @var{op0} and @var{op1}. @var{bit_code}\n\ is @code{AND} or @code{IOR}, which is the op on the two compares.", - rtx, (rtx prev, int cmp_code, rtx op0, rtx op1, int bit_code), + rtx, (rtx *prep_seq, rtx *gen_seq, rtx prev, int cmp_code, tree op0, tree op1, int bit_code), NULL) /* Return a new value for loop unroll size. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1ea322b..57e4936 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,77 @@ +2015-01-16 Ilya Enkovich <ilya.enkovich@intel.com> + + PR middle-end/64353 + * g++.dg/pr64353.C: New. + +2015-01-16 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + + PR target/64263 + * gcc.target/aarch64/pr64263_1.c: New test. + +2015-01-16 Yuri Rumyantsev <ysrumyan@gmail.com> + + PR tree-optimization/64434 + * gcc.dg/torture/pr64434.c: Move to... + * gcc.dg/pr64434.c: ... here. + +2015-01-16 Richard Biener <rguenther@suse.de> + + PR middle-end/64614 + * gcc.dg/uninit-18.c: New testcase. + +2015-01-16 Richard Biener <rguenther@suse.de> + + PR tree-optimization/64568 + * g++.dg/torture/pr64568-2.C: New testcase. + +2015-01-16 Ilya Enkovich <ilya.enkovich@intel.com> + + PR target/64363 + * gcc.target/i386/chkp-label-address.c: New. + +2015-01-16 Janus Weil <janus@gcc.gnu.org> + + PR fortran/45290 + * gfortran.dg/pointer_init_6.f90: Extended. + +2015-01-16 Robert Suchanek <robert.suchanek@imgtec.com> + + * gcc.c-torture/compile/20150108.c: New test. + +2015-01-16 Eric Botcazou <ebotcazou@adacore.com> + + * gcc.target/visium: New directory. + +2015-01-16 Richard Biener <rguenther@suse.de> + + PR tree-optimization/61743 + * gcc.dg/tree-ssa/pr61743-1.c: Add -fno-tree-vectorize. + * gcc.dg/tree-ssa/pr61743-2.c: Likewise. + +2015-01-16 Zhenqiang Chen <zhenqiang.chen@arm.com> + + * gcc.dg/pr64015.c: New test. + +2015-01-16 Markus Trippelsdorf <markus@trippelsdorf.de> + + PR ipa/64163 + PR ipa/64612 + * g++.dg/ipa/pr64612.C: New test. + +2015-01-16 Renlin Li <renlin.li@arm.com> + + * g++.dg/builtin-apply2.c: Remove aarch64 target from skip list. + +2015-01-16 Ilya Tocar <ilya.tocar@intel.com> + + * gcc.target/i386/sse-14.c: Test new intrinsic. + * gcc.target/i386/sse-22.c: Ditto. + +2015-01-16 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/58614 + * g++.dg/cpp0x/auto44.C: New. + 2015-01-15 Sandra Loosemore <sandra@codesourcery.com> PR target/59710 @@ -489,7 +563,7 @@ PR tree-optimization/64404 * gcc.dg/vect/pr64404.c: New testcase. -2014-01-13 Richard Biener <rguenther@suse.de> +2015-01-13 Richard Biener <rguenther@suse.de> PR tree-optimization/64568 * g++.dg/torture/pr64568.C: New testcase. diff --git a/gcc/testsuite/g++.dg/cpp0x/auto44.C b/gcc/testsuite/g++.dg/cpp0x/auto44.C new file mode 100644 index 0000000..687f154 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/auto44.C @@ -0,0 +1,10 @@ +// PR c++/58614 +// { dg-do compile { target c++11 } } + +#include <initializer_list> + +void foo() +{ + i; // { dg-error "not declared" } + auto j = { i }; // { dg-error "unable to deduce" } +} diff --git a/gcc/testsuite/g++.dg/ipa/pr64612.C b/gcc/testsuite/g++.dg/ipa/pr64612.C new file mode 100644 index 0000000..f1cd96a --- /dev/null +++ b/gcc/testsuite/g++.dg/ipa/pr64612.C @@ -0,0 +1,66 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -std=c++11" } */ +/* { dg-final { scan-assembler "_ZN5QListI7QStringED1Ev" } } */ + +class A +{ +public: + bool deref (); +}; +class QString; +struct B +{ + A ref; +}; +template <typename> class QList +{ + B d; +public: + ~QList (); + class const_iterator + { + }; + const_iterator constBegin (); + void clear (); + void dealloc (); +}; +template <typename T> QList<T>::~QList () +{ + if (d.ref.deref ()) + dealloc (); +} +template <typename T> +void +QList<T>::clear () +{ + QList (); +} +class A1 : public QList<QString> +{ +}; +class B1 +{ +public: + B1 (A1); +}; +struct F +{ + void addMatch (const QString &&); + A1 m_matchingMimeTypes; +}; +class G +{ + A1 matchingGlobs (const QString &) const; +}; +void +F::addMatch (const QString &&) +{ + m_matchingMimeTypes.clear (); +} +A1 +G::matchingGlobs (const QString &) const +{ + A1 a; + for (B1 b (a);;) + ; +} diff --git a/gcc/testsuite/g++.dg/pr64353.C b/gcc/testsuite/g++.dg/pr64353.C new file mode 100644 index 0000000..7859918 --- /dev/null +++ b/gcc/testsuite/g++.dg/pr64353.C @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +class C +{ + int y, x; + void i (); + bool __attribute__((const)) xx () { return x; } +}; + +void C::i () +{ + if (xx ()) + x = 1; +} diff --git a/gcc/testsuite/g++.dg/torture/pr64568-2.C b/gcc/testsuite/g++.dg/torture/pr64568-2.C new file mode 100644 index 0000000..0578217 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr64568-2.C @@ -0,0 +1,146 @@ +// { dg-do compile } + +namespace std +{ + typedef __SIZE_TYPE__ size_t; +} +class H; +namespace std +{ + template <typename> struct complex; + template <typename _Tp> + complex<_Tp> operator+(complex<_Tp> &__x, complex<_Tp> __y) + { + complex<_Tp> a = __x; + a += __y; + return a; + } + template <> struct complex<double> + { + int + imag () + { + return __imag__ _M_value; + } + void operator+=(complex __z) { _M_value += _M_value; _M_value += __z.imag (); } + _Complex double _M_value; + }; +} +struct A +{ + typedef std::complex<double> &const_reference; +}; +class B +{ +public: + B (int); + std::complex<double> &operator[](int i) { return data_[i]; } + std::complex<double> *data_; +}; +struct C +{ + static std::complex<double> + apply (A::const_reference t1, std::complex<double> t2) + { + return t1 + t2; + } + typedef std::complex<double> result_type; +}; +template <class T1, class> struct D +{ + static void + apply (T1 t1, std::complex<double> t2) + { + t1 = t2; + } +}; +class ublas_expression +{ +public: + ~ublas_expression (); +}; +template <class> class F +{ +}; +template <class E> class matrix_expression : ublas_expression +{ +public: + E &operator()() {} +}; +class I : public F<int> +{ +public: + typedef int value_type; + I (int); +}; +template <class E1, class E2> matrix_expression<int> outer_prod (F<E1>, F<E2>); +template <class E1, class F> class J : public matrix_expression<J<E1, F> > +{ +public: + typedef typename F::result_type value_type; + value_type operator()(int i, int) + { + return F::apply (e1_ (i, 0), e2_ (0, 0)); + } + E1 e1_; + E1 e2_; +}; +template <class E1, class E2> +J<H, C> operator+(matrix_expression<E1>, matrix_expression<E2>); +template <template <class, class> class F, class M, class E> +void +indexing_matrix_assign (M m, matrix_expression<E> e, int) +{ + for (int i; i; ++i) + F<typename M::reference, typename E::value_type>::apply (m (0, 0), + e ()(i, 0)); +} +template <template <class, class> class F, class, class M, class E, class C> +void +matrix_assign (M m, matrix_expression<E> e, int, C) +{ + indexing_matrix_assign<F> (m, e, 0); +} +template <template <class, class> class F, class M, class E> +void +matrix_assign (M m, matrix_expression<E> e) +{ + matrix_assign<F, int> (m, e, 0, typename M::orientation_category ()); +} +class H : matrix_expression<int> +{ +public: + typedef std::complex<double> &reference; + typedef int orientation_category; + H (int, int) : data_ (0) {} + template <class AE> H (matrix_expression<AE> ae) : data_ (0) + { + matrix_assign<D> (*this, ae); + } + B & + data () + { + } + std::complex<double> &operator()(int i, int) { return data ()[i]; } + void operator+=(matrix_expression ae) { H (*this + ae); } + B data_; +}; +template <class M, class T, class V1, class V2> +void +sr2 (M m, T, V1 v1, V2 v2) +{ + m += outer_prod (v2, v1); +} +template <class, class, std::size_t> struct G +{ + void test (); +}; +template struct G<I, H, 3>; +template <class V, class M, std::size_t N> +void +G<V, M, N>::test () +{ + V b (0), c (0); + M m (0, 0); + sr2 (m, typename V::value_type (), b, c); +} diff --git a/gcc/testsuite/gcc.c-torture/compile/20150108.c b/gcc/testsuite/gcc.c-torture/compile/20150108.c new file mode 100644 index 0000000..15c53e3 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/20150108.c @@ -0,0 +1,23 @@ +long long a[10]; +long long b, c, d, k, m, n, o, p, q, r, s, t, u, v, w; +int e, f, g, h, i, j, l, x; + +int fn1 () { + for (; x; x++) + if (x & 1) + s = h | g; + else + s = f | e; + l = ~0; + m = 1 | k; + n = i; + o = j; + p = f | e; + q = h | g; + w = d | c | a[1]; + t = c; + v = b | c; + u = v; + r = b | a[4]; + return e; +} diff --git a/gcc/testsuite/gcc.dg/builtin-apply2.c b/gcc/testsuite/gcc.dg/builtin-apply2.c index d666fcc..b6cbe39 100644 --- a/gcc/testsuite/gcc.dg/builtin-apply2.c +++ b/gcc/testsuite/gcc.dg/builtin-apply2.c @@ -1,6 +1,6 @@ /* { dg-do run } */ /* { dg-require-effective-target untyped_assembly } */ -/* { dg-skip-if "Variadic funcs have all args on stack. Normal funcs have args in registers." { "aarch64*-*-* avr-*-* nds32*-*-*" } { "*" } { "" } } */ +/* { dg-skip-if "Variadic funcs have all args on stack. Normal funcs have args in registers." { "avr-*-* nds32*-*-*" } { "*" } { "" } } */ /* { dg-skip-if "Variadic funcs use Base AAPCS. Normal funcs use VFP variant." { arm*-*-* && arm_hf_eabi } { "*" } { "" } } */ /* PR target/12503 */ diff --git a/gcc/testsuite/gcc.dg/pr64015.c b/gcc/testsuite/gcc.dg/pr64015.c new file mode 100644 index 0000000..daf8393 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr64015.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 " } */ + +int +test (unsigned short a, unsigned char b) +{ + return a > 0xfff2 && b > 252; +} + +/* { dg-final { scan-assembler "ccmp" { target aarch64*-*-* } } } */ diff --git a/gcc/testsuite/gcc.dg/torture/pr64434.c b/gcc/testsuite/gcc.dg/pr64434.c index 60fc806..60fc806 100644 --- a/gcc/testsuite/gcc.dg/torture/pr64434.c +++ b/gcc/testsuite/gcc.dg/pr64434.c diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr61743-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr61743-1.c index de09daa..5e45c2d 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr61743-1.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr61743-1.c @@ -1,5 +1,5 @@ /* { dg-do compile } */
-/* { dg-options "-O3 -funroll-loops -fdump-tree-cunroll-details" } */
+/* { dg-options "-O3 -funroll-loops -fno-tree-vectorize -fdump-tree-cunroll-details" } */
#define N 8
#define M 14
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr61743-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr61743-2.c index c8a4391..7bc8e35 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr61743-2.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr61743-2.c @@ -1,5 +1,5 @@ /* { dg-do compile } */
-/* { dg-options "-O3 -funroll-loops -fdump-tree-cunroll-details" } */
+/* { dg-options "-O3 -funroll-loops -fno-tree-vectorize -fdump-tree-cunroll-details" } */
#define N 8
#define M 14
diff --git a/gcc/testsuite/gcc.dg/uninit-18.c b/gcc/testsuite/gcc.dg/uninit-18.c new file mode 100644 index 0000000..223983e --- /dev/null +++ b/gcc/testsuite/gcc.dg/uninit-18.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O -Wuninitialized" } */ + +char *foo(int bar, char *baz) +{ + char *tmp; + + if (bar & 3) + tmp = baz; + + switch (bar) { + case 1: + tmp[5] = 7; /* { dg-bogus "may be used uninitialized" } */ + break; + case 2: + tmp[11] = 15; /* { dg-bogus "may be used uninitialized" } */ + break; + default: + tmp = 0; + break; + } + + return tmp; /* { dg-bogus "may be used uninitialized" } */ +} diff --git a/gcc/testsuite/gcc.target/aarch64/pr64263_1.c b/gcc/testsuite/gcc.target/aarch64/pr64263_1.c new file mode 100644 index 0000000..047e623 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/pr64263_1.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-O1" } */ + +#include "arm_neon.h" + +extern long int vget_lane_s64_1 (int64x1_t, const int); + +void +foo () +{ + int8x8_t val14; + int8x8_t val15; + uint8x8_t val16; + uint32x4_t val40; + val14 = vcreate_s8 (0xff0080f6807f807fUL); + val15 = vcreate_s8 (0x10807fff7f808080UL); + val16 = vcgt_s8 (val14, val15); + val40 = vreinterpretq_u32_u64 ( + vdupq_n_u64 ( + vget_lane_s64_1 ( + vreinterpret_s64_u8 (val16), 0) + )); +} diff --git a/gcc/testsuite/gcc.target/i386/chkp-label-address.c b/gcc/testsuite/gcc.target/i386/chkp-label-address.c new file mode 100644 index 0000000..05963e2 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/chkp-label-address.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target mpx } */ +/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -Wchkp" } */ + +#include <stdio.h> + +static int f1 () /* { dg-warning "function cannot be instrumented" "" } */ +{ + static int array = &&label_B - &&label_A; + + label_A: + + printf ("%d\n", array); + + label_B: + + return 0; +} + +int f2 (int i) +{ + printf ("%d\n", i); + return f1 (); +} diff --git a/gcc/testsuite/gcc.target/i386/sse-14.c b/gcc/testsuite/gcc.target/i386/sse-14.c index f3f6c5c..e8791e3 100644 --- a/gcc/testsuite/gcc.target/i386/sse-14.c +++ b/gcc/testsuite/gcc.target/i386/sse-14.c @@ -601,6 +601,8 @@ test_2 (_mm_alignr_pi8, __m64, __m64, __m64, 1) /* emmintrin.h */ test_2 (_mm_shuffle_pd, __m128d, __m128d, __m128d, 1) +test_1 (_mm_bsrli_si128, __m128i, __m128i, 1) +test_1 (_mm_bslli_si128, __m128i, __m128i, 1) test_1 (_mm_srli_si128, __m128i, __m128i, 1) test_1 (_mm_slli_si128, __m128i, __m128i, 1) test_1 (_mm_extract_epi16, int, __m128i, 1) diff --git a/gcc/testsuite/gcc.target/i386/sse-22.c b/gcc/testsuite/gcc.target/i386/sse-22.c index 0d7bd16..72017f5 100644 --- a/gcc/testsuite/gcc.target/i386/sse-22.c +++ b/gcc/testsuite/gcc.target/i386/sse-22.c @@ -138,6 +138,8 @@ test_1 (_mm_prefetch, void, void *, _MM_HINT_NTA) #endif #include <emmintrin.h> test_2 (_mm_shuffle_pd, __m128d, __m128d, __m128d, 1) +test_1 (_mm_bsrli_si128, __m128i, __m128i, 1) +test_1 (_mm_bslli_si128, __m128i, __m128i, 1) test_1 (_mm_srli_si128, __m128i, __m128i, 1) test_1 (_mm_slli_si128, __m128i, __m128i, 1) test_1 (_mm_extract_epi16, int, __m128i, 1) @@ -269,6 +271,8 @@ test_2 ( _mm256_blend_epi16, __m256i, __m256i, __m256i, 1) test_1 ( _mm256_shuffle_epi32, __m256i, __m256i, 1) test_1 ( _mm256_shufflehi_epi16, __m256i, __m256i, 1) test_1 ( _mm256_shufflelo_epi16, __m256i, __m256i, 1) +test_1 ( _mm256_bslli_epi128, __m256i, __m256i, 8) +test_1 ( _mm256_bsrli_epi128, __m256i, __m256i, 8) test_1 ( _mm256_slli_si256, __m256i, __m256i, 8) test_1 ( _mm256_srli_si256, __m256i, __m256i, 8) test_2 ( _mm_blend_epi32, __m128i, __m128i, __m128i, 1) diff --git a/gcc/testsuite/gcc.target/visium/bit_shift.c b/gcc/testsuite/gcc.target/visium/bit_shift.c new file mode 100644 index 0000000..bf37342 --- /dev/null +++ b/gcc/testsuite/gcc.target/visium/bit_shift.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +int bit_shift (long int x) +{ + int i, n; + + for (i = n = 0; x && (i < (sizeof(long) * 8)); ++i, x >>= 1) + n += (int)(x & 1L); + return n; +} + +/* { dg-final { scan-assembler-not "cmp" } } */ diff --git a/gcc/testsuite/gcc.target/visium/bit_test.c b/gcc/testsuite/gcc.target/visium/bit_test.c new file mode 100644 index 0000000..2de9208f --- /dev/null +++ b/gcc/testsuite/gcc.target/visium/bit_test.c @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +extern void bar (void); + +void foo1 (unsigned int i) +{ + if (i & 4) + bar (); +} + +void foo2 (unsigned int i) +{ + if (i & 0x80000000) + bar (); +} + +void foo3 (unsigned char c) +{ + if (c & 4) + bar (); +} + +void foo4 (unsigned char c) +{ + if (c & 0x80) + bar (); +} + +/* { dg-final { scan-assembler-times "lsr.l" 2 } } */ +/* { dg-final { scan-assembler-times "cmp" 2 } } */ diff --git a/gcc/testsuite/gcc.target/visium/block_move.c b/gcc/testsuite/gcc.target/visium/block_move.c new file mode 100644 index 0000000..a9e3522 --- /dev/null +++ b/gcc/testsuite/gcc.target/visium/block_move.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O -mcpu=gr6" } */ + +extern void abort (void); + +#define LEN 256 + +void foo (void) +{ + int dst[LEN], src[LEN]; + unsigned int i; + + __builtin_memset (src, 0, LEN * sizeof (int)); + __builtin_memcpy (dst, src, LEN * sizeof (int)); + if (__builtin_memcmp (dst, src, LEN * sizeof (int)) != 0) + abort (); +} + +/* { dg-final { scan-assembler "bmd" } } */ diff --git a/gcc/testsuite/gcc.target/visium/cstore_eq.c b/gcc/testsuite/gcc.target/visium/cstore_eq.c new file mode 100644 index 0000000..2bc132a --- /dev/null +++ b/gcc/testsuite/gcc.target/visium/cstore_eq.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +int foo1 (int i) +{ + return (i != 0); +} + +int foo2 (int i) +{ + return (i == 0); +} + +int foo3 (int a, int b) +{ + return a != b; +} + +int foo4 (int a, int b) +{ + return (a == b); +} + +/* { dg-final { scan-assembler-times "adc.l" 2 } } */ +/* { dg-final { scan-assembler-times "subc.l" 2 } } */ diff --git a/gcc/testsuite/gcc.target/visium/cstore_fp.c b/gcc/testsuite/gcc.target/visium/cstore_fp.c new file mode 100644 index 0000000..8849d1f --- /dev/null +++ b/gcc/testsuite/gcc.target/visium/cstore_fp.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fno-trapping-math" } */ + +int foo1 (float a, float b) +{ + return (a < b); +} + +int foo2 (float a, float b) +{ + return (a > b); +} + +int foo3 (float a, float b) +{ + return !(a < b); +} + +int foo4 (float a, float b) +{ + return !(a > b); +} + +/* { dg-final { scan-assembler-times "adc.l" 2 } } */ +/* { dg-final { scan-assembler-times "subc.l" 2 } } */ diff --git a/gcc/testsuite/gcc.target/visium/cstore_uns.c b/gcc/testsuite/gcc.target/visium/cstore_uns.c new file mode 100644 index 0000000..c60f984 --- /dev/null +++ b/gcc/testsuite/gcc.target/visium/cstore_uns.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +int foo1 (unsigned a, unsigned b) +{ + return (a < b); +} + +int foo2 (unsigned a, unsigned b) +{ + return (a > b); +} + +int foo3 (unsigned a, unsigned b) +{ + return (a >= b); +} + +int foo4 (unsigned a, unsigned b) +{ + return (a <= b); +} + +/* { dg-final { scan-assembler-times "adc.l" 2 } } */ +/* { dg-final { scan-assembler-times "subc.l" 2 } } */ diff --git a/gcc/testsuite/gcc.target/visium/long_branch.c b/gcc/testsuite/gcc.target/visium/long_branch.c new file mode 100644 index 0000000..a53537a --- /dev/null +++ b/gcc/testsuite/gcc.target/visium/long_branch.c @@ -0,0 +1,27 @@ +/* { dg-do assemble } */ + +volatile int k = 0; + +#define ONE k++; +#define TEN ONE ONE ONE ONE ONE ONE ONE ONE ONE ONE +#define HUN TEN TEN TEN TEN TEN TEN TEN TEN TEN TEN +#define THO HUN HUN HUN HUN HUN HUN HUN HUN HUN HUN +#define TTH THO THO THO THO THO THO THO THO THO THO THO + +void foo (void) +{ + start: + TTH + __asm__ __volatile__ ("" : : : "r28"); + goto start; +} + +#ifndef __OPTIMIZE__ +void bar (int i) +{ + if (i > 0) + { + TTH + } +} +#endif diff --git a/gcc/testsuite/gcc.target/visium/loop_clear.c b/gcc/testsuite/gcc.target/visium/loop_clear.c new file mode 100644 index 0000000..740e9d2 --- /dev/null +++ b/gcc/testsuite/gcc.target/visium/loop_clear.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +extern int a[]; + +void loop_clear (int i) +{ + while (i > 0) + a[i--] = 0; +} + +/* { dg-final { scan-assembler-times "cmp" 1 { xfail *-*-* } } } */ + +/* FIXME: the redundant cmp is not eliminated because the compare-elim pass + is run before the dbr pass. It's a regression wrt the cc0 port. */ diff --git a/gcc/testsuite/gcc.target/visium/visium.exp b/gcc/testsuite/gcc.target/visium/visium.exp new file mode 100644 index 0000000..5c179a7 --- /dev/null +++ b/gcc/testsuite/gcc.target/visium/visium.exp @@ -0,0 +1,44 @@ +# Specific regression driver for Visium. +# Copyright (C) 2015 Free Software Foundation, Inc. +# +# This file is part of GCC. +# +# GCC is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GCC is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# <http://www.gnu.org/licenses/>. */ + +# GCC testsuite that uses the `dg.exp' driver. + +# Exit immediately if this isn't a Visium target. +if {![istarget visium-*-*] } then { + return +} + +# Load support procs. +load_lib gcc-dg.exp + +# If a testcase doesn't have special options, use these. +global DEFAULT_CFLAGS +if ![info exists DEFAULT_CFLAGS] then { + set DEFAULT_CFLAGS " -ansi -pedantic-errors" +} + +# Initialize `dg'. +dg-init + +# Main loop. +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cCS\]]] \ + "" $DEFAULT_CFLAGS + +# All done. +dg-finish diff --git a/gcc/testsuite/gfortran.dg/pointer_init_6.f90 b/gcc/testsuite/gfortran.dg/pointer_init_6.f90 index 428a7de..f5e7555 100644 --- a/gcc/testsuite/gfortran.dg/pointer_init_6.f90 +++ b/gcc/testsuite/gfortran.dg/pointer_init_6.f90 @@ -16,6 +16,7 @@ module m1 integer, pointer :: p2 => p1 ! { dg-error "must have the TARGET attribute" } integer, pointer :: p3 => x%p ! { dg-error "must have the TARGET attribute" } integer, pointer :: p4 => x%i + integer, pointer :: p5 => u ! { dg-error "has no IMPLICIT type" } end module m1 diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 006bc08..2e23553 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -8754,7 +8754,7 @@ const pass_data pass_data_fixup_cfg = PROP_cfg, /* properties_required */ 0, /* properties_provided */ 0, /* properties_destroyed */ - 0, /* todo_flags_start */ + TODO_update_ssa_only_virtuals, /* todo_flags_start */ 0, /* todo_flags_finish */ }; diff --git a/gcc/tree-chkp.c b/gcc/tree-chkp.c index 45ac11e..e7649ef 100644 --- a/gcc/tree-chkp.c +++ b/gcc/tree-chkp.c @@ -1686,9 +1686,8 @@ chkp_add_bounds_to_call_stmt (gimple_stmt_iterator *gsi) && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_OBJECT_SIZE) return; - /* Do nothing for calls to legacy functions. */ - if (fndecl - && lookup_attribute ("bnd_legacy", DECL_ATTRIBUTES (fndecl))) + /* Do nothing for calls to not instrumentable functions. */ + if (fndecl && !chkp_instrumentable_p (fndecl)) return; /* Ignore CHKP_INIT_PTR_BOUNDS, CHKP_NULL_PTR_BOUNDS diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 5443ab5..d8abe03 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -3542,7 +3542,7 @@ has_label_address_in_static_1 (tree *nodep, int *walk_subtrees, void *fnp) /* Determine if the function can be copied. If so return NULL. If not return a string describng the reason for failure. */ -static const char * +const char * copy_forbidden (struct function *fun, tree fndecl) { const char *reason = fun->cannot_be_copied_reason; diff --git a/gcc/tree-inline.h b/gcc/tree-inline.h index 985d83b..f8b2ebf 100644 --- a/gcc/tree-inline.h +++ b/gcc/tree-inline.h @@ -234,6 +234,7 @@ extern tree remap_type (tree type, copy_body_data *id); extern gimple_seq copy_gimple_seq_and_replace_locals (gimple_seq seq); extern bool debug_find_tree (tree, tree); extern tree copy_fn (tree, tree&, tree&); +extern const char *copy_forbidden (struct function *fun, tree fndecl); /* This is in tree-inline.c since the routine uses data structures from the inliner. */ diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c index a4140e5..82d832d 100644 --- a/gcc/tree-ssa-forwprop.c +++ b/gcc/tree-ssa-forwprop.c @@ -2230,6 +2230,8 @@ pass_forwprop::execute (function *fun) else if (TREE_CODE (TREE_TYPE (lhs)) == COMPLEX_TYPE && gimple_assign_load_p (stmt) && !gimple_has_volatile_ops (stmt) + && (TREE_CODE (gimple_assign_rhs1 (stmt)) + != TARGET_MEM_REF) && !stmt_can_throw_internal (stmt)) { /* Rewrite loads used only in real/imagpart extractions to diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c index da40088..25aae19 100644 --- a/gcc/tree-ssa-uninit.c +++ b/gcc/tree-ssa-uninit.c @@ -58,6 +58,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-pass.h" #include "diagnostic-core.h" #include "params.h" +#include "tree-cfg.h" /* This implements the pass that does predicate aware warning on uses of possibly uninitialized variables. The pass first collects the set of @@ -411,6 +412,7 @@ find_control_equiv_block (basic_block bb) #define MAX_NUM_CHAINS 8 #define MAX_CHAIN_LEN 5 #define MAX_POSTDOM_CHECK 8 +#define MAX_SWITCH_CASES 40 /* Computes the control dependence chains (paths of edges) for DEP_BB up to the dominating basic block BB (the head node of a @@ -592,17 +594,63 @@ convert_control_dep_chain_into_preds (vec<edge> *dep_chains, if (skip) continue; } - if (gimple_code (cond_stmt) != GIMPLE_COND) + if (gimple_code (cond_stmt) == GIMPLE_COND) + { + one_pred.pred_lhs = gimple_cond_lhs (cond_stmt); + one_pred.pred_rhs = gimple_cond_rhs (cond_stmt); + one_pred.cond_code = gimple_cond_code (cond_stmt); + one_pred.invert = !!(e->flags & EDGE_FALSE_VALUE); + t_chain.safe_push (one_pred); + has_valid_pred = true; + } + else if (gswitch *gs = dyn_cast <gswitch *> (cond_stmt)) + { + /* Avoid quadratic behavior. */ + if (gimple_switch_num_labels (gs) > MAX_SWITCH_CASES) + { + has_valid_pred = false; + break; + } + /* Find the case label. */ + tree l = NULL_TREE; + unsigned idx; + for (idx = 0; idx < gimple_switch_num_labels (gs); ++idx) + { + tree tl = gimple_switch_label (gs, idx); + if (e->dest == label_to_block (CASE_LABEL (tl))) + { + if (!l) + l = tl; + else + { + l = NULL_TREE; + break; + } + } + } + /* If more than one label reaches this block or the case + label doesn't have a single value (like the default one) + fail. */ + if (!l + || !CASE_LOW (l) + || (CASE_HIGH (l) && !operand_equal_p (CASE_LOW (l), + CASE_HIGH (l), 0))) + { + has_valid_pred = false; + break; + } + one_pred.pred_lhs = gimple_switch_index (gs); + one_pred.pred_rhs = CASE_LOW (l); + one_pred.cond_code = EQ_EXPR; + one_pred.invert = false; + t_chain.safe_push (one_pred); + has_valid_pred = true; + } + else { has_valid_pred = false; break; } - one_pred.pred_lhs = gimple_cond_lhs (cond_stmt); - one_pred.pred_rhs = gimple_cond_rhs (cond_stmt); - one_pred.cond_code = gimple_cond_code (cond_stmt); - one_pred.invert = !!(e->flags & EDGE_FALSE_VALUE); - t_chain.safe_push (one_pred); - has_valid_pred = true; } if (!has_valid_pred) @@ -1329,6 +1377,10 @@ is_pred_expr_subset_of (pred_info expr1, pred_info expr2) if (expr2.invert) code2 = invert_tree_comparison (code2, false); + if (code1 == EQ_EXPR && code2 == BIT_AND_EXPR) + return wi::eq_p (expr1.pred_rhs, + wi::bit_and (expr1.pred_rhs, expr2.pred_rhs)); + if (code1 != code2 && code2 != NE_EXPR) return false; @@ -1970,8 +2022,25 @@ normalize_one_pred_1 (pred_chain_union *norm_preds, } else if (gimple_assign_rhs_code (def_stmt) == and_or_code) { - push_to_worklist (gimple_assign_rhs1 (def_stmt), work_list, mark_set); - push_to_worklist (gimple_assign_rhs2 (def_stmt), work_list, mark_set); + /* Avoid splitting up bit manipulations like x & 3 or y | 1. */ + if (is_gimple_min_invariant (gimple_assign_rhs2 (def_stmt))) + { + /* But treat x & 3 as condition. */ + if (and_or_code == BIT_AND_EXPR) + { + pred_info n_pred; + n_pred.pred_lhs = gimple_assign_rhs1 (def_stmt); + n_pred.pred_rhs = gimple_assign_rhs2 (def_stmt); + n_pred.cond_code = and_or_code; + n_pred.invert = false; + norm_chain->safe_push (n_pred); + } + } + else + { + push_to_worklist (gimple_assign_rhs1 (def_stmt), work_list, mark_set); + push_to_worklist (gimple_assign_rhs2 (def_stmt), work_list, mark_set); + } } else if (TREE_CODE_CLASS (gimple_assign_rhs_code (def_stmt)) == tcc_comparison) diff --git a/libatomic/ChangeLog b/libatomic/ChangeLog index b0c72d3..ef5b6cd 100644 --- a/libatomic/ChangeLog +++ b/libatomic/ChangeLog @@ -1,3 +1,9 @@ +2015-01-16 Ilya Verbin <ilya.verbin@intel.com> + + PR testsuite/64605 + * testsuite/lib/libatomic.exp: Do not load gcc-dg.exp. + * testsuite/libatomic.c/c.exp: Load gcc-dg.exp. + 2015-01-09 Andreas Tobler <andreast@gcc.gnu.org> * configure.tgt: Exclude arm*-*-freebsd* from try_ifunc. diff --git a/libatomic/testsuite/lib/libatomic.exp b/libatomic/testsuite/lib/libatomic.exp index 28cbaa8..0491c18 100644 --- a/libatomic/testsuite/lib/libatomic.exp +++ b/libatomic/testsuite/lib/libatomic.exp @@ -23,6 +23,11 @@ proc load_gcc_lib { filename } { } load_lib dg.exp + +# Required to use gcc-dg.exp - however, the latter should NOT be +# loaded until ${tool}_target_compile is defined since it uses that +# to determine default LTO options. + load_gcc_lib file-format.exp load_gcc_lib target-supports.exp load_gcc_lib target-utils.exp @@ -40,7 +45,6 @@ load_gcc_lib torture-options.exp load_gcc_lib timeout.exp load_gcc_lib timeout-dg.exp load_gcc_lib fortran-modules.exp -load_gcc_lib gcc-dg.exp set dg-do-what-default run diff --git a/libatomic/testsuite/libatomic.c/c.exp b/libatomic/testsuite/libatomic.c/c.exp index 1da3cb1..dbdb5eb 100644 --- a/libatomic/testsuite/libatomic.c/c.exp +++ b/libatomic/testsuite/libatomic.c/c.exp @@ -21,6 +21,7 @@ if [info exists lang_test_file] then { } load_lib libatomic-dg.exp +load_gcc_lib gcc-dg.exp # If a testcase doesn't have special options, use these. if ![info exists DEFAULT_CFLAGS] then { diff --git a/libgo/Makefile.am b/libgo/Makefile.am index 0ce3576..4195981 100644 --- a/libgo/Makefile.am +++ b/libgo/Makefile.am @@ -762,6 +762,9 @@ else if LIBGO_IS_DARWIN go_net_tcpsockopt_file = go/net/tcpsockopt_darwin.go else +if LIBGO_IS_SOLARIS +go_net_tcpsockopt_file = go/net/tcpsockopt_solaris.go +else if LIBGO_IS_DRAGONFLY go_net_tcpsockopt_file = go/net/tcpsockopt_dragonfly.go else @@ -769,6 +772,7 @@ go_net_tcpsockopt_file = go/net/tcpsockopt_unix.go endif endif endif +endif go_net_files = \ go/net/cgo_unix.go \ diff --git a/libgo/Makefile.in b/libgo/Makefile.in index 495dc35..af8566f 100644 --- a/libgo/Makefile.in +++ b/libgo/Makefile.in @@ -1019,8 +1019,9 @@ go_mime_files = \ @LIBGO_IS_LINUX_TRUE@go_net_interface_file = go/net/interface_linux.go @LIBGO_IS_LINUX_FALSE@go_net_cloexec_file = go/net/sys_cloexec.go @LIBGO_IS_LINUX_TRUE@go_net_cloexec_file = go/net/sock_cloexec.go -@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_OPENBSD_FALSE@go_net_tcpsockopt_file = go/net/tcpsockopt_unix.go -@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_DRAGONFLY_TRUE@@LIBGO_IS_OPENBSD_FALSE@go_net_tcpsockopt_file = go/net/tcpsockopt_dragonfly.go +@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_tcpsockopt_file = go/net/tcpsockopt_unix.go +@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_DRAGONFLY_TRUE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_tcpsockopt_file = go/net/tcpsockopt_dragonfly.go +@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_tcpsockopt_file = go/net/tcpsockopt_solaris.go @LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_OPENBSD_FALSE@go_net_tcpsockopt_file = go/net/tcpsockopt_darwin.go @LIBGO_IS_OPENBSD_TRUE@go_net_tcpsockopt_file = go/net/tcpsockopt_openbsd.go go_net_files = \ diff --git a/libgo/go/net/tcpsockopt_solaris.go b/libgo/go/net/tcpsockopt_solaris.go new file mode 100644 index 0000000..eaab6b6 --- /dev/null +++ b/libgo/go/net/tcpsockopt_solaris.go @@ -0,0 +1,27 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// TCP socket options for solaris + +package net + +import ( + "os" + "syscall" + "time" +) + +// Set keep alive period. +func setKeepAlivePeriod(fd *netFD, d time.Duration) error { + if err := fd.incref(); err != nil { + return err + } + defer fd.decref() + + // The kernel expects seconds so round to next highest second. + d += (time.Second - time.Nanosecond) + secs := int(d.Seconds()) + + return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.SO_KEEPALIVE, secs)) +} diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog index 9b003cb..7c106d4 100644 --- a/libgomp/ChangeLog +++ b/libgomp/ChangeLog @@ -1,3 +1,7 @@ +2015-01-16 Gerald Pfeifer <gerald@pfeifer.com> + + * target.c (num_devices): Guard with PLUGIN_SUPPORT. + 2015-01-15 Thomas Schwinge <thomas@codesourcery.com> James Norris <jnorris@codesourcery.com> Tom de Vries <tom@codesourcery.com> diff --git a/libgomp/target.c b/libgomp/target.c index 83ad511..72d64fc 100644 --- a/libgomp/target.c +++ b/libgomp/target.c @@ -63,8 +63,10 @@ static int num_offload_images; /* Array of descriptors for all available devices. */ static struct gomp_device_descr *devices; +#ifdef PLUGIN_SUPPORT /* Total number of available devices. */ static int num_devices; +#endif /* Number of GOMP_OFFLOAD_CAP_OPENMP_400 devices. */ static int num_devices_openmp; diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index df00984..7e68c45 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,28 @@ +2015-01-16 Jonathan Wakely <jwakely@redhat.com> + + * acinclude.m4: Fix typo in comment. + * configure: Regenerate. + * include/bits/codecvt.h (codecvt<char16_t, char, mbstate_t>, + codecvt<char16_t, char, mbstate_t>): Declare specializations. + * include/bits/locale_facets.h: Reserve space for new specializations. + * src/c++11/Makefile.am: Add codecvt.cc. + * src/c++11/Makefile.in: Regenerate. + * src/c++11/codecvt.cc: New. + * src/c++98/Makefile.am: Compile locale_init.cc and localename.cc + with -std=gnu++11. + * src/c++98/Makefile.in: Regenerate. + * src/c++98/locale_init.cc: Initialize new codecvt specializations. + * src/c++98/localename.cc: Likewise. + * config/abi/pre/gnu.ver: Exports for new codecvt specializations. + * testsuite/22_locale/codecvt/utf8.cc: New. + * testsuite/22_locale/locale/cons/unicode.cc: Check that new + specializations are installed in locale objects. + +2015-01-16 Torvald Riegel <triegel@redhat.com> + + * include/std/shared_mutex (shared_timed_mutex): Add POSIX-based + implementation. + 2015-01-13 Jonathan Wakely <jwakely@redhat.com> PR libstdc++/64571 diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4 index db357d6..74e8eaf 100644 --- a/libstdc++-v3/acinclude.m4 +++ b/libstdc++-v3/acinclude.m4 @@ -1777,7 +1777,7 @@ AC_DEFUN([GLIBCXX_CHECK_C99_TR1], [ <tr1/cinttypes> in namespace std::tr1.]) fi - # Check for the existence of whcar_t <inttypes.h> functions (NB: doesn't + # Check for the existence of wchar_t <inttypes.h> functions (NB: doesn't # make sense if the glibcxx_cv_c99_stdint_tr1 check fails, per C99, 7.8/1). ac_c99_inttypes_wchar_t_tr1=no; if test x"$glibcxx_cv_c99_stdint_tr1" = x"yes"; then diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver index 700da18..83f4e8c 100644 --- a/libstdc++-v3/config/abi/pre/gnu.ver +++ b/libstdc++-v3/config/abi/pre/gnu.ver @@ -1759,6 +1759,11 @@ GLIBCXX_3.4.21 { _ZNKSt8time_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEE3getES3_S3_RSt8ios_baseRSt12_Ios_IostateP2tmPK[cw]SC_; _ZNKSt8time_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEE6do_getES3_S3_RSt8ios_baseRSt12_Ios_IostateP2tmcc; + # codecvt<char16_t, char, mbstate_t>, codecvt<char32_t, char, mbstate_t> + _ZNKSt7codecvtID[is]c11__mbstate_t*; + _ZNSt7codecvtID[is]c11__mbstate_t*; + _ZT[ISV]St7codecvtID[is]c11__mbstate_tE; + } GLIBCXX_3.4.20; diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure index be9337fc..7bd1ede 100755 --- a/libstdc++-v3/configure +++ b/libstdc++-v3/configure @@ -19216,7 +19216,7 @@ $as_echo "#define _GLIBCXX_USE_C99_INTTYPES_TR1 1" >>confdefs.h fi - # Check for the existence of whcar_t <inttypes.h> functions (NB: doesn't + # Check for the existence of wchar_t <inttypes.h> functions (NB: doesn't # make sense if the glibcxx_cv_c99_stdint_tr1 check fails, per C99, 7.8/1). ac_c99_inttypes_wchar_t_tr1=no; if test x"$glibcxx_cv_c99_stdint_tr1" = x"yes"; then diff --git a/libstdc++-v3/include/bits/codecvt.h b/libstdc++-v3/include/bits/codecvt.h index 1eee1cc..a6e59b5 100644 --- a/libstdc++-v3/include/bits/codecvt.h +++ b/libstdc++-v3/include/bits/codecvt.h @@ -393,7 +393,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION }; #ifdef _GLIBCXX_USE_WCHAR_T - /// class codecvt<wchar_t, char, mbstate_t> specialization. + /** @brief Class codecvt<wchar_t, char, mbstate_t> specialization. + * + * Converts between narrow and wide characters in the native character set + */ template<> class codecvt<wchar_t, char, mbstate_t> : public __codecvt_abstract_base<wchar_t, char, mbstate_t> @@ -455,6 +458,125 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION }; #endif //_GLIBCXX_USE_WCHAR_T +#if __cplusplus >= 201103L +#ifdef _GLIBCXX_USE_C99_STDINT_TR1 + /** @brief Class codecvt<char16_t, char, mbstate_t> specialization. + * + * Converts between UTF-16 and UTF-8. + */ + template<> + class codecvt<char16_t, char, mbstate_t> + : public __codecvt_abstract_base<char16_t, char, mbstate_t> + { + public: + // Types: + typedef char16_t intern_type; + typedef char extern_type; + typedef mbstate_t state_type; + + public: + static locale::id id; + + explicit + codecvt(size_t __refs = 0) + : __codecvt_abstract_base<char16_t, char, mbstate_t>(__refs) { } + + protected: + virtual + ~codecvt(); + + virtual result + do_out(state_type& __state, const intern_type* __from, + const intern_type* __from_end, const intern_type*& __from_next, + extern_type* __to, extern_type* __to_end, + extern_type*& __to_next) const; + + virtual result + do_unshift(state_type& __state, + extern_type* __to, extern_type* __to_end, + extern_type*& __to_next) const; + + virtual result + do_in(state_type& __state, + const extern_type* __from, const extern_type* __from_end, + const extern_type*& __from_next, + intern_type* __to, intern_type* __to_end, + intern_type*& __to_next) const; + + virtual + int do_encoding() const throw(); + + virtual + bool do_always_noconv() const throw(); + + virtual + int do_length(state_type&, const extern_type* __from, + const extern_type* __end, size_t __max) const; + + virtual int + do_max_length() const throw(); + }; + + /** @brief Class codecvt<char32_t, char, mbstate_t> specialization. + * + * Converts between UTF-32 and UTF-8. + */ + template<> + class codecvt<char32_t, char, mbstate_t> + : public __codecvt_abstract_base<char32_t, char, mbstate_t> + { + public: + // Types: + typedef char32_t intern_type; + typedef char extern_type; + typedef mbstate_t state_type; + + public: + static locale::id id; + + explicit + codecvt(size_t __refs = 0) + : __codecvt_abstract_base<char32_t, char, mbstate_t>(__refs) { } + + protected: + virtual + ~codecvt(); + + virtual result + do_out(state_type& __state, const intern_type* __from, + const intern_type* __from_end, const intern_type*& __from_next, + extern_type* __to, extern_type* __to_end, + extern_type*& __to_next) const; + + virtual result + do_unshift(state_type& __state, + extern_type* __to, extern_type* __to_end, + extern_type*& __to_next) const; + + virtual result + do_in(state_type& __state, + const extern_type* __from, const extern_type* __from_end, + const extern_type*& __from_next, + intern_type* __to, intern_type* __to_end, + intern_type*& __to_next) const; + + virtual + int do_encoding() const throw(); + + virtual + bool do_always_noconv() const throw(); + + virtual + int do_length(state_type&, const extern_type* __from, + const extern_type* __end, size_t __max) const; + + virtual int + do_max_length() const throw(); + }; + +#endif // _GLIBCXX_USE_C99_STDINT_TR1 +#endif // C++11 + /// class codecvt_byname [22.2.1.6]. template<typename _InternT, typename _ExternT, typename _StateT> class codecvt_byname : public codecvt<_InternT, _ExternT, _StateT> diff --git a/libstdc++-v3/include/bits/locale_facets.h b/libstdc++-v3/include/bits/locale_facets.h index a5fc45e..77932a5 100644 --- a/libstdc++-v3/include/bits/locale_facets.h +++ b/libstdc++-v3/include/bits/locale_facets.h @@ -59,6 +59,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION # define _GLIBCXX_NUM_FACETS 14 # define _GLIBCXX_NUM_CXX11_FACETS 8 #endif +#ifdef _GLIBCXX_USE_C99_STDINT_TR1 +# define _GLIBCXX_NUM_UNICODE_FACETS 2 +#else +# define _GLIBCXX_NUM_UNICODE_FACETS 0 +#endif // Convert string to numeric value of type _Tp and store results. // NB: This is specialized for all required types, there is no diff --git a/libstdc++-v3/include/std/shared_mutex b/libstdc++-v3/include/std/shared_mutex index 8bfede3..643768c 100644 --- a/libstdc++-v3/include/std/shared_mutex +++ b/libstdc++-v3/include/std/shared_mutex @@ -57,6 +57,188 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// shared_timed_mutex class shared_timed_mutex { +#if defined(__GTHREADS_CXX0X) + typedef chrono::system_clock __clock_t; + + pthread_rwlock_t _M_rwlock; + + public: + shared_timed_mutex() + { + int __ret = pthread_rwlock_init(&_M_rwlock, NULL); + if (__ret == ENOMEM) + throw bad_alloc(); + else if (__ret == EAGAIN) + __throw_system_error(int(errc::resource_unavailable_try_again)); + else if (__ret == EPERM) + __throw_system_error(int(errc::operation_not_permitted)); + // Errors not handled: EBUSY, EINVAL + _GLIBCXX_DEBUG_ASSERT(__ret == 0); + } + + ~shared_timed_mutex() + { + int __ret __attribute((unused)) = pthread_rwlock_destroy(&_M_rwlock); + // Errors not handled: EBUSY, EINVAL + _GLIBCXX_DEBUG_ASSERT(__ret == 0); + } + + shared_timed_mutex(const shared_timed_mutex&) = delete; + shared_timed_mutex& operator=(const shared_timed_mutex&) = delete; + + // Exclusive ownership + + void + lock() + { + int __ret = pthread_rwlock_wrlock(&_M_rwlock); + if (__ret == EDEADLK) + __throw_system_error(int(errc::resource_deadlock_would_occur)); + // Errors not handled: EINVAL + _GLIBCXX_DEBUG_ASSERT(__ret == 0); + } + + bool + try_lock() + { + int __ret = pthread_rwlock_trywrlock(&_M_rwlock); + if (__ret == EBUSY) return false; + // Errors not handled: EINVAL + _GLIBCXX_DEBUG_ASSERT(__ret == 0); + return true; + } + + template<typename _Rep, typename _Period> + bool + try_lock_for(const chrono::duration<_Rep, _Period>& __rel_time) + { + return try_lock_until(__clock_t::now() + __rel_time); + } + + template<typename _Duration> + bool + try_lock_until(const chrono::time_point<__clock_t, _Duration>& __atime) + { + auto __s = chrono::time_point_cast<chrono::seconds>(__atime); + auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s); + + __gthread_time_t __ts = + { + static_cast<std::time_t>(__s.time_since_epoch().count()), + static_cast<long>(__ns.count()) + }; + + int __ret = pthread_rwlock_timedwrlock(&_M_rwlock, &__ts); + // On self-deadlock, we just fail to acquire the lock. Technically, + // the program violated the precondition. + if (__ret == ETIMEDOUT || __ret == EDEADLK) + return false; + // Errors not handled: EINVAL + _GLIBCXX_DEBUG_ASSERT(__ret == 0); + return true; + } + + template<typename _Clock, typename _Duration> + bool + try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time) + { + // DR 887 - Sync unknown clock to known clock. + const typename _Clock::time_point __c_entry = _Clock::now(); + const __clock_t::time_point __s_entry = __clock_t::now(); + const auto __delta = __abs_time - __c_entry; + const auto __s_atime = __s_entry + __delta; + return try_lock_until(__s_atime); + } + + void + unlock() + { + int __ret __attribute((unused)) = pthread_rwlock_unlock(&_M_rwlock); + // Errors not handled: EPERM, EBUSY, EINVAL + _GLIBCXX_DEBUG_ASSERT(__ret == 0); + } + + // Shared ownership + + void + lock_shared() + { + int __ret = pthread_rwlock_rdlock(&_M_rwlock); + if (__ret == EDEADLK) + __throw_system_error(int(errc::resource_deadlock_would_occur)); + if (__ret == EAGAIN) + // Maximum number of read locks has been exceeded. + __throw_system_error(int(errc::device_or_resource_busy)); + // Errors not handled: EINVAL + _GLIBCXX_DEBUG_ASSERT(__ret == 0); + } + + bool + try_lock_shared() + { + int __ret = pthread_rwlock_tryrdlock(&_M_rwlock); + // If the maximum number of read locks has been exceeded, we just fail + // to acquire the lock. Unlike for lock(), we are not allowed to throw + // an exception. + if (__ret == EBUSY || __ret == EAGAIN) return false; + // Errors not handled: EINVAL + _GLIBCXX_DEBUG_ASSERT(__ret == 0); + return true; + } + + template<typename _Rep, typename _Period> + bool + try_lock_shared_for(const chrono::duration<_Rep, _Period>& __rel_time) + { + return try_lock_shared_until(__clock_t::now() + __rel_time); + } + + template<typename _Duration> + bool + try_lock_shared_until(const chrono::time_point<__clock_t, + _Duration>& __atime) + { + auto __s = chrono::time_point_cast<chrono::seconds>(__atime); + auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s); + + __gthread_time_t __ts = + { + static_cast<std::time_t>(__s.time_since_epoch().count()), + static_cast<long>(__ns.count()) + }; + + int __ret = pthread_rwlock_timedrdlock(&_M_rwlock, &__ts); + // If the maximum number of read locks has been exceeded, or we would + // deadlock, we just fail to acquire the lock. Unlike for lock(), + // we are not allowed to throw an exception. + if (__ret == ETIMEDOUT || __ret == EAGAIN || __ret == EDEADLK) + return false; + // Errors not handled: EINVAL + _GLIBCXX_DEBUG_ASSERT(__ret == 0); + return true; + } + + template<typename _Clock, typename _Duration> + bool + try_lock_shared_until(const chrono::time_point<_Clock, + _Duration>& __abs_time) + { + // DR 887 - Sync unknown clock to known clock. + const typename _Clock::time_point __c_entry = _Clock::now(); + const __clock_t::time_point __s_entry = __clock_t::now(); + const auto __delta = __abs_time - __c_entry; + const auto __s_atime = __s_entry + __delta; + return try_lock_shared_until(__s_atime); + } + + void + unlock_shared() + { + unlock(); + } + +#else // defined(__GTHREADS_CXX0X) + #if _GTHREAD_USE_MUTEX_TIMEDLOCK struct _Mutex : mutex, __timed_mutex_impl<_Mutex> { @@ -252,6 +434,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_gate1.notify_one(); } } +#endif // !defined(__GTHREADS_CXX0X) }; #endif // _GLIBCXX_HAS_GTHREADS diff --git a/libstdc++-v3/src/c++11/Makefile.am b/libstdc++-v3/src/c++11/Makefile.am index 4cba983..b57e552 100644 --- a/libstdc++-v3/src/c++11/Makefile.am +++ b/libstdc++-v3/src/c++11/Makefile.am @@ -53,6 +53,7 @@ endif sources = \ chrono.cc \ + codecvt.cc \ condition_variable.cc \ cow-stdexcept.cc \ ctype.cc \ diff --git a/libstdc++-v3/src/c++11/Makefile.in b/libstdc++-v3/src/c++11/Makefile.in index 619bf37..00a5c25 100644 --- a/libstdc++-v3/src/c++11/Makefile.in +++ b/libstdc++-v3/src/c++11/Makefile.in @@ -72,12 +72,12 @@ libc__11convenience_la_LIBADD = @ENABLE_DUAL_ABI_TRUE@ cxx11-ios_failure.lo \ @ENABLE_DUAL_ABI_TRUE@ cxx11-shim_facets.lo cxx11-stdexcept.lo am__objects_2 = ctype_configure_char.lo ctype_members.lo -am__objects_3 = chrono.lo condition_variable.lo cow-stdexcept.lo \ - ctype.lo debug.lo functexcept.lo functional.lo future.lo \ - hash_c++0x.lo hashtable_c++0x.lo ios.lo limits.lo mutex.lo \ - placeholders.lo random.lo regex.lo shared_ptr.lo \ - snprintf_lite.lo system_error.lo thread.lo $(am__objects_1) \ - $(am__objects_2) +am__objects_3 = chrono.lo codecvt.lo condition_variable.lo \ + cow-stdexcept.lo ctype.lo debug.lo functexcept.lo \ + functional.lo future.lo hash_c++0x.lo hashtable_c++0x.lo \ + ios.lo limits.lo mutex.lo placeholders.lo random.lo regex.lo \ + shared_ptr.lo snprintf_lite.lo system_error.lo thread.lo \ + $(am__objects_1) $(am__objects_2) @ENABLE_DUAL_ABI_TRUE@am__objects_4 = cow-fstream-inst.lo \ @ENABLE_DUAL_ABI_TRUE@ cow-sstream-inst.lo cow-string-inst.lo \ @ENABLE_DUAL_ABI_TRUE@ cow-wstring-inst.lo cxx11-locale-inst.lo \ @@ -344,6 +344,7 @@ host_sources = \ sources = \ chrono.cc \ + codecvt.cc \ condition_variable.cc \ cow-stdexcept.cc \ ctype.cc \ diff --git a/libstdc++-v3/src/c++11/codecvt.cc b/libstdc++-v3/src/c++11/codecvt.cc new file mode 100644 index 0000000..fdd4972 --- /dev/null +++ b/libstdc++-v3/src/c++11/codecvt.cc @@ -0,0 +1,461 @@ +// Locale support (codecvt) -*- C++ -*- + +// Copyright (C) 2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +#include <bits/locale_classes.h> +#include <bits/codecvt.h> +#include <bits/stl_algobase.h> // std::max +#include <cstring> // std::memcpy, std::memcmp + +#ifdef _GLIBCXX_USE_C99_STDINT_TR1 +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +namespace +{ + // Largest code point that fits in a single UTF-16 code unit. + const char32_t max_single_utf16_unit = 0xFFFF; + const char32_t max_code_point = 0x10FFFF; + + template<typename Elem> + struct range + { + Elem* next; + Elem* end; + + Elem operator*() const { return *next; } + + range& operator++() { ++next; return *this; } + + size_t size() const { return end - next; } + }; + + char32_t + read_utf8_code_point(range<const char>& from, unsigned long maxcode) + { + size_t avail = from.size(); + if (avail == 0) + return -1; + unsigned char c1 = from.next[0]; + // https://en.wikipedia.org/wiki/UTF-8#Sample_code + if (c1 < 0x80) + { + ++from.next; + return c1; + } + else if (c1 < 0xC2) // continuation or overlong 2-byte sequence + return -1; + else if (c1 < 0xE0) // 2-byte sequence + { + if (avail < 2) + return -1; + unsigned char c2 = from.next[1]; + if ((c2 & 0xC0) != 0x80) + return -1; + char32_t c = (c1 << 6) + c2 - 0x3080; + if (c > maxcode) + return -1; + from.next += 2; + return c; + } + else if (c1 < 0xF0) // 3-byte sequence + { + if (avail < 3) + return -1; + unsigned char c2 = from.next[1]; + if ((c2 & 0xC0) != 0x80) + return -1; + if (c1 == 0xE0 && c2 < 0xA0) // overlong + return -1; + unsigned char c3 = from.next[2]; + if ((c3 & 0xC0) != 0x80) + return -1; + char32_t c = (c1 << 12) + (c2 << 6) + c3 - 0xE2080; + if (c > maxcode) + return -1; + from.next += 3; + return c; + } + else if (c1 < 0xF5) // 4-byte sequence + { + if (avail < 4) + return -1; + unsigned char c2 = from.next[1]; + if ((c2 & 0xC0) != 0x80) + return -1; + if (c1 == 0xF0 && c2 < 0x90) // overlong + return -1; + if (c1 == 0xF4 && c2 >= 0x90) // > U+10FFFF + return -1; + unsigned char c3 = from.next[2]; + if ((c3 & 0xC0) != 0x80) + return -1; + unsigned char c4 = from.next[3]; + if ((c4 & 0xC0) != 0x80) + return -1; + char32_t c = (c1 << 18) + (c2 << 12) + (c3 << 6) + c4 - 0x3C82080; + if (c > maxcode) + return -1; + from.next += 4; + return c; + } + else // > U+10FFFF + return -1; + } + + bool + write_utf8_code_point(range<char>& to, char32_t code_point) + { + if (code_point < 0x80) + { + if (to.size() < 1) + return false; + *to.next++ = code_point; + } + else if (code_point <= 0x7FF) + { + if (to.size() < 2) + return false; + *to.next++ = (code_point >> 6) + 0xC0; + *to.next++ = (code_point & 0x3F) + 0x80; + } + else if (code_point <= 0xFFFF) + { + if (to.size() < 3) + return false; + *to.next++ = (code_point >> 12) + 0xE0; + *to.next++ = ((code_point >> 6) & 0x3F) + 0x80; + *to.next++ = (code_point & 0x3F) + 0x80; + } + else if (code_point <= 0x10FFFF) + { + if (to.size() < 4) + return false; + *to.next++ = (code_point >> 18) + 0xF0; + *to.next++ = ((code_point >> 12) & 0x3F) + 0x80; + *to.next++ = ((code_point >> 6) & 0x3F) + 0x80; + *to.next++ = (code_point & 0x3F) + 0x80; + } + else + return false; + return true; + } + + bool + write_utf16_code_point(range<char16_t>& to, char32_t codepoint) + { + if (codepoint < max_single_utf16_unit) + { + if (to.size() > 0) + { + *to.next = codepoint; + ++to.next; + return true; + } + } + else if (to.size() > 1) + { + // Algorithm from http://www.unicode.org/faq/utf_bom.html#utf16-4 + const char32_t LEAD_OFFSET = 0xD800 - (0x10000 >> 10); + const char32_t SURROGATE_OFFSET = 0x10000 - (0xD800 << 10) - 0xDC00; + char16_t lead = LEAD_OFFSET + (codepoint >> 10); + char16_t trail = 0xDC00 + (codepoint & 0x3FF); + char32_t utf16bytes = (lead << 10) + trail + SURROGATE_OFFSET; + + to.next[0] = utf16bytes >> 16; + to.next[1] = utf16bytes & 0xFFFF; + to.next += 2; + return true; + } + return false; + } + + // utf8 -> ucs4 + codecvt_base::result + ucs4_in(range<const char>& from, range<char32_t>& to, + unsigned long maxcode = max_code_point) + { + while (from.size() && to.size()) + { + const char32_t codepoint = read_utf8_code_point(from, maxcode); + if (codepoint == char32_t(-1) || codepoint > maxcode) + return codecvt_base::error; + *to.next++ = codepoint; + } + return from.size() ? codecvt_base::partial : codecvt_base::ok; + } + + // ucs4 -> utf8 + codecvt_base::result + ucs4_out(range<const char32_t>& from, range<char>& to, + unsigned long maxcode = max_code_point) + { + while (from.size()) + { + const char32_t c = from.next[0]; + if (c > maxcode) + return codecvt_base::error; + if (!write_utf8_code_point(to, c)) + return codecvt_base::partial; + ++from.next; + } + return codecvt_base::ok; + } + + // utf8 -> utf16 + codecvt_base::result + utf16_in(range<const char>& from, range<char16_t>& to, + unsigned long maxcode = max_code_point) + { + while (from.size() && to.size()) + { + const char* first = from.next; + if ((unsigned char)*first >= 0xF0 && to.size() < 2) + return codecvt_base::partial; + const char32_t codepoint = read_utf8_code_point(from, maxcode); + if (codepoint == char32_t(-1) || codepoint > maxcode) + return codecvt_base::error; + if (!write_utf16_code_point(to, codepoint)) + { + from.next = first; + return codecvt_base::partial; + } + } + return codecvt_base::ok; + } + + // utf16 -> utf8 + codecvt_base::result + utf16_out(range<const char16_t>& from, range<char>& to, + unsigned long maxcode = max_code_point) + { + while (from.size()) + { + char32_t c = from.next[0]; + int inc = 1; + if (c >= 0xD800 && c < 0xDBFF) // start of surrogate pair + { + if (from.size() < 2) + return codecvt_base::ok; // stop converting at this point + + const char32_t c2 = from.next[1]; + if (c2 >= 0xDC00 && c2 <= 0xDFFF) + { + inc = 2; + c = (c << 10) + c2 - 0x35FDC00; + } + else + return codecvt_base::error; + } + if (c > maxcode) + return codecvt_base::error; + if (!write_utf8_code_point(to, c)) + return codecvt_base::partial; + from.next += inc; + } + return codecvt_base::ok; + } + + // return pos such that [begin,pos) is valid UTF-16 string no longer than max + int + utf16_len(const char* begin, const char* end, size_t max, + char32_t maxcode = max_code_point) + { + range<const char> from{ begin, end }; + size_t count = 0; + while (count+1 < max) + { + char32_t c = read_utf8_code_point(from, maxcode); + if (c == char32_t(-1)) + break; + else if (c > max_single_utf16_unit) + ++count; + ++count; + } + if (count+1 == max) // take one more character if it fits in a single unit + read_utf8_code_point(from, std::max(max_single_utf16_unit, maxcode)); + return from.next - begin; + } + + // return pos such that [begin,pos) is valid UCS-4 string no longer than max + int + ucs4_len(const char* begin, const char* end, size_t max, + char32_t maxcode = max_code_point) + { + range<const char> from{ begin, end }; + size_t count = 0; + while (count < max) + { + char32_t c = read_utf8_code_point(from, maxcode); + if (c == char32_t(-1)) + break; + ++count; + } + return from.next - begin; + } +} + +// Define members of codecvt<char16_t, char, mbstate_t> specialization. +// Converts from UTF-8 to UTF-16. + +locale::id codecvt<char16_t, char, mbstate_t>::id; + +codecvt<char16_t, char, mbstate_t>::~codecvt() { } + +codecvt_base::result +codecvt<char16_t, char, mbstate_t>:: +do_out(state_type&, + const intern_type* __from, + const intern_type* __from_end, const intern_type*& __from_next, + extern_type* __to, extern_type* __to_end, + extern_type*& __to_next) const +{ + range<const char16_t> from{ __from, __from_end }; + range<char> to{ __to, __to_end }; + auto res = utf16_out(from, to); + __from_next = from.next; + __to_next = to.next; + return res; +} + +codecvt_base::result +codecvt<char16_t, char, mbstate_t>:: +do_unshift(state_type&, extern_type* __to, extern_type*, + extern_type*& __to_next) const +{ + __to_next = __to; + return noconv; // we don't use mbstate_t for the unicode facets +} + +codecvt_base::result +codecvt<char16_t, char, mbstate_t>:: +do_in(state_type&, const extern_type* __from, const extern_type* __from_end, + const extern_type*& __from_next, + intern_type* __to, intern_type* __to_end, + intern_type*& __to_next) const +{ + range<const char> from{ __from, __from_end }; + range<char16_t> to{ __to, __to_end }; + auto res = utf16_in(from, to); + __from_next = from.next; + __to_next = to.next; + return res; +} + +int +codecvt<char16_t, char, mbstate_t>::do_encoding() const throw() +{ return 0; } + +bool +codecvt<char16_t, char, mbstate_t>::do_always_noconv() const throw() +{ return false; } + +int +codecvt<char16_t, char, mbstate_t>:: +do_length(state_type&, const extern_type* __from, + const extern_type* __end, size_t __max) const +{ + return utf16_len(__from, __end, __max); +} + +int +codecvt<char16_t, char, mbstate_t>::do_max_length() const throw() +{ + // Any valid UTF-8 sequence of 3 bytes fits in a single 16-bit code unit, + // whereas 4 byte sequences require two 16-bit code units. + return 3; +} + +// Define members of codecvt<char32_t, char, mbstate_t> specialization. +// Converts from UTF-8 to UTF-32 (aka UCS-4). + +locale::id codecvt<char32_t, char, mbstate_t>::id; + +codecvt<char32_t, char, mbstate_t>::~codecvt() { } + +codecvt_base::result +codecvt<char32_t, char, mbstate_t>:: +do_out(state_type&, const intern_type* __from, const intern_type* __from_end, + const intern_type*& __from_next, + extern_type* __to, extern_type* __to_end, + extern_type*& __to_next) const +{ + range<const char32_t> from{ __from, __from_end }; + range<char> to{ __to, __to_end }; + auto res = ucs4_out(from, to); + __from_next = from.next; + __to_next = to.next; + return res; +} + +codecvt_base::result +codecvt<char32_t, char, mbstate_t>:: +do_unshift(state_type&, extern_type* __to, extern_type*, + extern_type*& __to_next) const +{ + __to_next = __to; + return noconv; +} + +codecvt_base::result +codecvt<char32_t, char, mbstate_t>:: +do_in(state_type&, const extern_type* __from, const extern_type* __from_end, + const extern_type*& __from_next, + intern_type* __to, intern_type* __to_end, + intern_type*& __to_next) const +{ + range<const char> from{ __from, __from_end }; + range<char32_t> to{ __to, __to_end }; + auto res = ucs4_in(from, to); + __from_next = from.next; + __to_next = to.next; + return res; +} + +int +codecvt<char32_t, char, mbstate_t>::do_encoding() const throw() +{ return 0; } + +bool +codecvt<char32_t, char, mbstate_t>::do_always_noconv() const throw() +{ return false; } + +int +codecvt<char32_t, char, mbstate_t>:: +do_length(state_type&, const extern_type* __from, + const extern_type* __end, size_t __max) const +{ + return ucs4_len(__from, __end, __max); +} + +int +codecvt<char32_t, char, mbstate_t>::do_max_length() const throw() +{ return 4; } + +inline template class __codecvt_abstract_base<char16_t, char, mbstate_t>; +inline template class __codecvt_abstract_base<char32_t, char, mbstate_t>; + +_GLIBCXX_END_NAMESPACE_VERSION +} +#endif // _GLIBCXX_USE_C99_STDINT_TR1 diff --git a/libstdc++-v3/src/c++98/Makefile.am b/libstdc++-v3/src/c++98/Makefile.am index 6dd7a72..e348dfb 100644 --- a/libstdc++-v3/src/c++98/Makefile.am +++ b/libstdc++-v3/src/c++98/Makefile.am @@ -176,6 +176,16 @@ numeric_members_cow.o: numeric_members_cow.cc $(CXXCOMPILE) $(GLIBCXX_ABI_FLAGS) -fimplicit-templates -c $< endif +# XXX TODO move locale_init.cc and localename.cc to src/c++11 +locale_init.lo: locale_init.cc + $(LTCXXCOMPILE) -std=gnu++11 -c $< +locale_init.o: locale_init.cc + $(LTCXXCOMPILE) -std=gnu++11 -c $< +localename.lo: localename.cc + $(LTCXXCOMPILE) -std=gnu++11 -c $< +localename.o: localename.cc + $(LTCXXCOMPILE) -std=gnu++11 -c $< + # Use special rules for the deprecated source files so that they find # deprecated include files. GLIBCXX_INCLUDE_DIR=$(glibcxx_builddir)/include diff --git a/libstdc++-v3/src/c++98/Makefile.in b/libstdc++-v3/src/c++98/Makefile.in index 9a2a27f..3c69791 100644 --- a/libstdc++-v3/src/c++98/Makefile.in +++ b/libstdc++-v3/src/c++98/Makefile.in @@ -764,6 +764,16 @@ vpath % $(top_srcdir)/src/c++98 @ENABLE_DUAL_ABI_TRUE@ $(LTCXXCOMPILE) $(GLIBCXX_ABI_FLAGS) -fimplicit-templates -c $< @ENABLE_DUAL_ABI_TRUE@numeric_members_cow.o: numeric_members_cow.cc @ENABLE_DUAL_ABI_TRUE@ $(CXXCOMPILE) $(GLIBCXX_ABI_FLAGS) -fimplicit-templates -c $< + +# XXX TODO move locale_init.cc and localename.cc to src/c++11 +locale_init.lo: locale_init.cc + $(LTCXXCOMPILE) -std=gnu++11 -c $< +locale_init.o: locale_init.cc + $(LTCXXCOMPILE) -std=gnu++11 -c $< +localename.lo: localename.cc + $(LTCXXCOMPILE) -std=gnu++11 -c $< +localename.o: localename.cc + $(LTCXXCOMPILE) -std=gnu++11 -c $< strstream.lo: strstream.cc $(LTCXXCOMPILE) -I$(GLIBCXX_INCLUDE_DIR)/backward -Wno-deprecated -c $< strstream.o: strstream.cc diff --git a/libstdc++-v3/src/c++98/locale_init.cc b/libstdc++-v3/src/c++98/locale_init.cc index c45eff3..0a95b9f 100644 --- a/libstdc++-v3/src/c++98/locale_init.cc +++ b/libstdc++-v3/src/c++98/locale_init.cc @@ -57,7 +57,7 @@ _GLIBCXX_LOC_ID(_ZNSt8messagesIwE2idE); namespace { - const int num_facets = _GLIBCXX_NUM_FACETS + const int num_facets = _GLIBCXX_NUM_FACETS + _GLIBCXX_NUM_UNICODE_FACETS + (_GLIBCXX_USE_DUAL_ABI ? _GLIBCXX_NUM_CXX11_FACETS : 0); __gnu_cxx::__mutex& @@ -201,6 +201,16 @@ namespace fake_messages_w messages_w; #endif +#ifdef _GLIBCXX_USE_C99_STDINT_TR1 + typedef char fake_codecvt_c16[sizeof(codecvt<char16_t, char, mbstate_t>)] + __attribute__ ((aligned(__alignof__(codecvt<char16_t, char, mbstate_t>)))); + fake_codecvt_c16 codecvt_c16; + + typedef char fake_codecvt_c32[sizeof(codecvt<char32_t, char, mbstate_t>)] + __attribute__ ((aligned(__alignof__(codecvt<char32_t, char, mbstate_t>)))); + fake_codecvt_c32 codecvt_c32; +#endif + // Storage for "C" locale caches. typedef char fake_num_cache_c[sizeof(std::__numpunct_cache<char>)] __attribute__ ((aligned(__alignof__(std::__numpunct_cache<char>)))); @@ -319,6 +329,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION &std::ctype<wchar_t>::id, &codecvt<wchar_t, char, mbstate_t>::id, #endif +#ifdef _GLIBCXX_USE_C99_STDINT_TR1 + &codecvt<char16_t, char, mbstate_t>::id, + &codecvt<char32_t, char, mbstate_t>::id, +#endif 0 }; @@ -522,6 +536,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_init_facet(new (&messages_w) std::messages<wchar_t>(1)); #endif +#ifdef _GLIBCXX_USE_C99_STDINT_TR1 + _M_init_facet(new (&codecvt_c16) codecvt<char16_t, char, mbstate_t>(1)); + _M_init_facet(new (&codecvt_c32) codecvt<char32_t, char, mbstate_t>(1)); +#endif + #if _GLIBCXX_USE_DUAL_ABI facet* extra[] = { __npc, __mpcf, __mpct # ifdef _GLIBCXX_USE_WCHAR_T diff --git a/libstdc++-v3/src/c++98/localename.cc b/libstdc++-v3/src/c++98/localename.cc index c42a217..2884bee 100644 --- a/libstdc++-v3/src/c++98/localename.cc +++ b/libstdc++-v3/src/c++98/localename.cc @@ -171,7 +171,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } } -const int num_facets = _GLIBCXX_NUM_FACETS +const int num_facets = _GLIBCXX_NUM_FACETS + _GLIBCXX_NUM_UNICODE_FACETS + (_GLIBCXX_USE_DUAL_ABI ? _GLIBCXX_NUM_CXX11_FACETS : 0); // Construct named _Impl. @@ -267,7 +267,12 @@ const int num_facets = _GLIBCXX_NUM_FACETS _M_init_facet(new time_get<wchar_t>); _M_init_facet(new time_put<wchar_t>); _M_init_facet(new std::messages<wchar_t>(__cloc, __s)); -#endif +#endif + +#ifdef _GLIBCXX_USE_C99_STDINT_TR1 + _M_init_facet(new codecvt<char16_t, char, mbstate_t>); + _M_init_facet(new codecvt<char32_t, char, mbstate_t>); +#endif #if _GLIBCXX_USE_DUAL_ABI _M_init_extra(&__cloc, &__clocm, __s, __smon); diff --git a/libstdc++-v3/testsuite/22_locale/codecvt/utf8.cc b/libstdc++-v3/testsuite/22_locale/codecvt/utf8.cc new file mode 100644 index 0000000..987233a --- /dev/null +++ b/libstdc++-v3/testsuite/22_locale/codecvt/utf8.cc @@ -0,0 +1,76 @@ +// Copyright (C) 2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-require-cstdint "" } +// { dg-options "-std=gnu++11" } + +#include <locale> +#include <iterator> +#include <string> +#include <testsuite_hooks.h> + +const char expected[] = u8"£¥€"; +const std::size_t expected_len = std::char_traits<char>::length(expected); + +template<typename C> +void test(const C* from) +{ + auto len = std::char_traits<C>::length(from); + std::mbstate_t state{}; + char buf[16] = { }; + using test_type = std::codecvt<C, char, std::mbstate_t>; + const test_type& cvt = std::use_facet<test_type>(std::locale::classic()); + auto from_end = from + len; + auto from_next = from; + auto buf_end = std::end(buf); + auto buf_next = buf; + auto res = cvt.out(state, from, from_end, from_next, buf, buf_end, buf_next); + VERIFY( res == std::codecvt_base::ok ); + VERIFY( from_next == from_end ); + VERIFY( (buf_next - buf) == expected_len ); + VERIFY( 0 == std::char_traits<char>::compare(buf, expected, expected_len) ); + + C buf2[16]; + auto exp_end = expected + expected_len; + auto exp_next = expected; + auto buf2_end = std::end(buf2); + auto buf2_next = buf2; + res = cvt.in(state, expected, exp_end, exp_next, buf2, buf2_end, buf2_next); + VERIFY( res == std::codecvt_base::ok ); + VERIFY( exp_next == exp_end ); + VERIFY( (buf2_next - buf2) == len ); + VERIFY( 0 == std::char_traits<C>::compare(buf2, from, len) ); +} + +void +test01() +{ + test(u"£¥€"); +} + +void +test02() +{ + test(U"£¥€"); +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/22_locale/locale/cons/unicode.cc b/libstdc++-v3/testsuite/22_locale/locale/cons/unicode.cc index b6f8c8b..33b5a8a 100644 --- a/libstdc++-v3/testsuite/22_locale/locale/cons/unicode.cc +++ b/libstdc++-v3/testsuite/22_locale/locale/cons/unicode.cc @@ -1,4 +1,5 @@ // { dg-require-iconv "ISO-8859-1" } +// { dg-options "-std=gnu++11" } // Copyright (C) 2006-2015 Free Software Foundation, Inc. // @@ -32,6 +33,11 @@ typedef std::codecvt<char, char, std::mbstate_t> c_codecvt; typedef std::codecvt<wchar_t, char, std::mbstate_t> w_codecvt; #endif +#ifdef _GLIBCXX_USE_C99_STDINT_TR1 +typedef std::codecvt<char16_t, char, std::mbstate_t> u16_codecvt; +typedef std::codecvt<char32_t, char, std::mbstate_t> u32_codecvt; +#endif + class gnu_facet: public std::locale::facet { public: @@ -61,6 +67,10 @@ void test01() #ifdef _GLIBCXX_USE_WCHAR_T VERIFY( has_facet<w_codecvt>(loc13) ); #endif +#ifdef _GLIBCXX_USE_C99_STDINT_TR1 + VERIFY( has_facet<u16_codecvt>(loc13) ); + VERIFY( has_facet<u32_codecvt>(loc13) ); +#endif VERIFY( has_facet<unicode_codecvt>(loc13) ); } catch(...) |