diff options
author | Martin Liska <mliska@suse.cz> | 2021-05-26 09:18:21 +0200 |
---|---|---|
committer | Martin Liska <mliska@suse.cz> | 2021-05-26 09:18:21 +0200 |
commit | b1edeaddf3b48278724f3175983b9f357d437874 (patch) | |
tree | ca0f4fbad20f6d9cba1662acb1bb507f3341835c | |
parent | 2f7ea01554b7d202f169fc4268d8c9ee2fabbad2 (diff) | |
parent | 0eac9c60ac1f28eeb7bb0a56e533865d984015f6 (diff) | |
download | gcc-b1edeaddf3b48278724f3175983b9f357d437874.zip gcc-b1edeaddf3b48278724f3175983b9f357d437874.tar.gz gcc-b1edeaddf3b48278724f3175983b9f357d437874.tar.bz2 |
Merge branch 'master' into devel/sphinx
39 files changed, 1239 insertions, 923 deletions
diff --git a/c++tools/ChangeLog b/c++tools/ChangeLog index 0fa6214..c0228cb 100644 --- a/c++tools/ChangeLog +++ b/c++tools/ChangeLog @@ -1,3 +1,22 @@ +2021-05-25 Jakub Jelinek <jakub@redhat.com> + + PR bootstrap/100731 + * server.cc: Include <cstdlib>. + +2021-05-25 Eric Botcazou <ebotcazou@adacore.com> + + * configure.ac (--enable-maintainer-mode): Fix typo and weird syntax. + * configure: Regenerate. + +2021-05-25 Jakub Jelinek <jakub@redhat.com> + + * Makefile.in: Update copyright year. + * configure.ac: Likewise. + * resolver.cc: Likewise. + * resolver.h: Likewise. + * server.cc: Likewise. + (print_version): Update copyright notice date. + 2021-05-10 Martin Liska <mliska@suse.cz> * Makefile.in: Include also ../gcc folder. diff --git a/c++tools/server.cc b/c++tools/server.cc index 709955e..fae3e78 100644 --- a/c++tools/server.cc +++ b/c++tools/server.cc @@ -29,6 +29,7 @@ along with GCC; see the file COPYING3. If not see #include <csignal> #include <cstring> #include <cstdarg> +#include <cstdlib> // OS #include <unistd.h> #include <sys/types.h> diff --git a/contrib/ChangeLog b/contrib/ChangeLog index 0498c0f..a07fc19 100644 --- a/contrib/ChangeLog +++ b/contrib/ChangeLog @@ -1,3 +1,7 @@ +2021-05-25 Jakub Jelinek <jakub@redhat.com> + + * update-copyright.py: Add c++tools. + 2021-05-24 Martin Liska <mliska@suse.cz> * gcc-changelog/git_commit.py: Add note that ChangeLog entries diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d3c90e2..897c704 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,297 @@ +2021-05-25 Andrew MacLeod <amacleod@redhat.com> + + * gimple-range-gori.cc (class logical_stmt_cache): Delete + (logical_stmt_cache::logical_stmt_cache ): Delete. + (logical_stmt_cache::~logical_stmt_cache): Delete. + (logical_stmt_cache::cache_entry::dump): Delete. + (logical_stmt_cache::get_range): Delete. + (logical_stmt_cache::cached_name ): Delete. + (logical_stmt_cache::same_cached_name): Delete. + (logical_stmt_cache::cacheable_p): Delete. + (logical_stmt_cache::slot_diagnostics ): Delete. + (logical_stmt_cache::dump): Delete. + (gori_compute_cache::gori_compute_cache): Delete. + (gori_compute_cache::~gori_compute_cache): Delete. + (gori_compute_cache::compute_operand_range): Delete. + (gori_compute_cache::cache_stmt): Delete. + * gimple-range-gori.h (gori_compute::compute_operand_range): Remove + virtual. + (class gori_compute_cache): Delete. + +2021-05-25 Andrew MacLeod <amacleod@redhat.com> + + * gimple-range.cc (fold_using_range::range_of_range_op): Use m_gori + intead of m_cache. + (fold_using_range::range_of_address): Adjust. + (fold_using_range::range_of_phi): Adjust. + * gimple-range.h (class fur_source): Adjust. + (fur_source::fur_source): Adjust. + +2021-05-25 Andrew MacLeod <amacleod@redhat.com> + + * gimple-range-gori.cc (gori_compute::expr_range_at_stmt): Rename + from expr_range_in_bb and adjust. + (gori_compute::compute_name_range_op): Adjust. + (gori_compute::optimize_logical_operands): Adjust. + (gori_compute::compute_logical_operands_in_chain): Adjust. + (gori_compute::compute_operand1_range): Adjust. + (gori_compute::compute_operand2_range): Adjust. + (ori_compute_cache::cache_stmt): Adjust. + * gimple-range-gori.h (gori_compute): Rename prototype. + +2021-05-25 Andrew MacLeod <amacleod@redhat.com> + + * gimple-range.cc (gimple_ranger::range_of_expr): Non-null should be + checked only after range_of_stmt, not range_on_entry. + (gimple_ranger::range_on_entry): Check for non-null in any + predecessor block, if it is not already non-null. + (gimple_ranger::range_on_exit): DOnt check for non-null after + range on entry call. + (gimple_ranger::dump_bb): New. Split from dump. + (gimple_ranger::dump): Adjust. + * gimple-range.h (class gimple_ranger): Adjust. + +2021-05-25 Andrew MacLeod <amacleod@redhat.com> + + * gimple-range-cache.cc (struct range_timestamp): Delete. + (class temporal_cache): Adjust. + (temporal_cache::get_timestamp): Delete. + (temporal_cache::set_dependency): Delete. + (temporal_cache::temporal_value): Adjust. + (temporal_cache::current_p): Take dependencies as params. + (temporal_cache::set_timestamp): Adjust. + (temporal_cache::set_always_current): Adjust. + (ranger_cache::get_non_stale_global_range): Adjust. + (ranger_cache::register_dependency): Delete. + * gimple-range-cache.h (class range_cache): Adjust. + +2021-05-25 Andrew MacLeod <amacleod@redhat.com> + + * gimple-range-gori.cc (range_def_chain::range_def_chain): init + bitmap obstack. + (range_def_chain::~range_def_chain): Dispose of obstack rather than + each individual bitmap. + (range_def_chain::set_import): New. + (range_def_chain::get_imports): New. + (range_def_chain::chain_import_p): New. + (range_def_chain::register_dependency): Rename from build_def_chain + and set imports. + (range_def_chain::def_chain_in_bitmap_p): New. + (range_def_chain::add_def_chain_to_bitmap): New. + (range_def_chain::has_def_chain): Just check first depenedence. + (range_def_chain::get_def_chain): Process imports, use generic + register_dependency routine. + (range_def_chain::dump): New. + (gori_map::gori_map): Allocate import list. + (gori_map::~gori_map): Release imports. + (gori_map::exports): Check for past allocated block size. + (gori_map::imports): New. + (gori_map::def_chain_in_export_p): Delete. + (gori_map::is_import_p): New. + (gori_map::maybe_add_gori): Handle imports. + (gori_map::dump): Adjust output, add imports. + (gori_compute::has_edge_range_p): Remove def_chain_in_export call. + (gori_export_iterator::gori_export_iterator): New. + (gori_export_iterator::next): New. + (gori_export_iterator::get_name): New. + * gimple-range-gori.h (range_def_chain): Add imports and direct + dependecies via struct rdc. + (range_def_chain::depend1): New. + (range_def_chain::depend2): New. + (class gori_map): Adjust. + (FOR_EACH_GORI_IMPORT_NAME): New. + (FOR_EACH_GORI_EXPORT_NAME): New. + (class gori_export_iterator): New. + +2021-05-25 Andrew MacLeod <amacleod@redhat.com> + + * gimple-range-cache.cc (ranger_cache::ranger_cache): Move initial + export cache filling to here. + * gimple-range-gori.cc (gori_compute::gori_compute) : From Here. + +2021-05-25 Andrew MacLeod <amacleod@redhat.com> + + * gimple-range-gori.cc (range_def_chain): Move to gimple-range-gori.h. + (gori_map): Move to gimple-range-gori.h. + (gori_compute::gori_compute): Adjust. + (gori_compute::~gori_compute): Delete. + (gori_compute::compute_operand_range_switch): Adjust. + (gori_compute::compute_operand_range): Adjust. + (gori_compute::compute_logical_operands): Adjust. + (gori_compute::has_edge_range_p ): Adjust. + (gori_compute::set_range_invariant): Delete. + (gori_compute::dump): Adjust. + (gori_compute::outgoing_edge_range_p): Adjust. + * gimple-range-gori.h (class range_def_chain): Relocate here. + (class gori_map): Relocate here. + (class gori_compute): Inherit from gori_map, and adjust. + +2021-05-25 Aldy Hernandez <aldyh@redhat.com> + + * value-range.cc (range_tests_legacy): Use + build_nonstandard_integer_type instead of int and short. + +2021-05-25 Eric Botcazou <ebotcazou@adacore.com> + + * gimplify.c (gimplify_decl_expr): Clear TREE_READONLY on the DECL + when really creating an initialization statement for it. + +2021-05-25 Eric Botcazou <ebotcazou@adacore.com> + + * tree-inline.c (setup_one_parameter): Fix thinko in new condition. + +2021-05-25 Kito Cheng <kito.cheng@sifive.com> + + * config/riscv/riscv.h (ASM_SPEC): Pass -mno-relax. + +2021-05-25 Martin Liska <mliska@suse.cz> + + PR tree-optimization/92860 + PR target/99592 + * optc-save-gen.awk: Remove exceptions. + +2021-05-25 Martin Liska <mliska@suse.cz> + + * asan.h (sanitize_coverage_p): New function. + * doc/extend.texi: Document it. + * fold-const.c (fold_range_test): Use sanitize_flags_p + instead of flag_sanitize_coverage. + (fold_truth_andor): Likewise. + * sancov.c: Likewise. + * tree-ssa-ifcombine.c (ifcombine_ifandif): Likewise. + * ipa-inline.c (sanitize_attrs_match_for_inline_p): Handle + -fsanitize-coverage when inlining. + +2021-05-25 Cooper Qu <cooper.qu@linux.alibaba.com> + + * config/csky/csky-modes.def : Fix copyright. + +2021-05-25 Cooper Qu <cooper.qu@linux.alibaba.com> + + * config/csky/csky-modes.def : Amend copyright. + * config/csky/csky_insn_fpuv2.md : Likewise. + * config/csky/csky_insn_fpuv3.md : Likewise. + +2021-05-25 Richard Biener <rguenther@suse.de> + + PR middle-end/100727 + * calls.c (initialize_argument_information): Explicitely test + for WITH_SIZE_EXPR. + * gimple-expr.c (mark_addressable): Skip outer WITH_SIZE_EXPR. + +2021-05-25 Geng Qi <gengqi@linux.alibaba.com> + + * config/csky/csky.h (FRAME_POINTER_REGNUM): Use + HARD_FRAME_POINTER_REGNUM and FRAME_POINTER_REGNUM instead of + the signle definition. The signle definition may not work well + at simplify_subreg_regno(). + (HARD_FRAME_POINTER_REGNUM): New. + (ELIMINABLE_REGS): Add for HARD_FRAME_POINTER_REGNUM. + * config/csky/csky.c (get_csky_live_regs, csky_can_eliminate, + csky_initial_elimination_offset, csky_expand_prologue, + csky_expand_epilogue): Add for HARD_FRAME_POINTER_REGNUM. + +2021-05-25 Geng Qi <gengqi@linux.alibaba.com> + + * config/csky/csky.c (csky_option_override): + Init csky_arch_isa_features[] in advance, so TARGET_DSP + and TARGET_DIV can be set well. + +2021-05-25 Geng Qi <gengqi@linux.alibaba.com> + + * config/csky/constraints.md ("l", "h"): Delete. + * config/csky/csky.h (reg_class, REG_CLASS_NAMES, + REG_CLASS_CONTENTS): Delete LO_REGS and HI_REGS. + * config/csky/csky.c (regno_reg_classm, + csky_secondary_reload, csky_register_move_cost): + Use HILO_REGS instead of LO_REGS and HI_REGS. + +2021-05-25 Geng Qi <gengqi@linux.alibaba.com> + + * config/csky/constraints.md ("W"): New constriant for mem operand + with base reg, index register. + ("Q"): Renamed and modified "csky_valid_fpuv2_mem_operand" to + "csky_valid_mem_constraint_operand" to deal with both "Q" and "W" + constraint. + ("Dv"): New constraint for const double value that can be used at + fmovi instruction. + * config/csky/csky-modes.def (HFmode): New mode. + * config/csky/csky-protos.h (csky_valid_fpuv2_mem_operand): Rename + to "csky_valid_mem_constraint_operand" and support new constraint + "W". + (csky_get_movedouble_length): New. + (fpuv3_output_move): New. + (fpuv3_const_double): New. + * config/csky/csky.c (csky_option_override): New arch CK860 with fpv3. + (decompose_csky_address): Refine. + (csky_print_operand): New "CONST_DOUBLE" operand. + (csky_output_move): Support fpv3 instructions. + (csky_get_movedouble_length): New. + (fpuv3_output_move): New. + (fpuv3_const_double): New. + (csky_emit_compare): Cover float comparsion. + (csky_emit_compare_float): Refine. + (csky_vaild_fpuv2_mem_operand): Rename to + "csky_valid_mem_constraint_operand" and support new constraint "W". + (ck860_rtx_costs): New. + (csky_rtx_costs): Add the cost calculation of CK860. + (regno_reg_class): New vregs for fpuv3. + (csky_dbx_regno): Likewise. + (csky_cpu_cpp_builtins): New builtin macro for fpuv3. + (csky_conditional_register_usage): Suporrot fpuv3. + (csky_dwarf_register_span): Suporrot fpuv3. + (csky_init_builtins, csky_mangle_type): Support "__fp16" type. + (ck810_legitimate_index_p): Support fp16. + * config/csky/csky.h (TARGET_TLS): ADD CK860. + (CSKY_VREG_P, CSKY_VREG_LO_P, CSKY_VREG_HI_P): Support fpuv3. + (TARGET_SINGLE_FPU): Support fpuv3. + (TARGET_SUPPORT_FPV3): New. + (FIRST_PSEUDO_REGISTER): Change to 202 to hold the new fpuv3 registers. + (FIXED_REGISTERS, CALL_REALLY_USED_REGISTERS, REGISTER_NAMES, + REG_CLASS_CONTENTS): Support fpuv3. + * config/csky/csky.md (movsf): Move to cksy_insn_fpu.md and refine. + (csky_movsf_fpv2): Likewise. + (ck801_movsf): Likewise. + (csky_movsf): Likewise. + (movdf): Likewise. + (csky_movdf_fpv2): Likewise. + (ck801_movdf): Likewise. + (csky_movdf): Likewise. + (movsicc): Refine. Use "comparison_operatior" instead of + "ordered_comparison_operatior". + (addsicc): Likewise. + (CSKY_FIRST_VFP3_REGNUM, CSKY_LAST_VFP3_REGNUM): New constant. + (call_value_internal_vh): New. + * config/csky/csky_cores.def (CK860): New arch and cpu. + (fpv3_hf): New. + (fpv3_hsf): New. + (fpv3_sdf): New. + (fpv3): New. + * config/csky/csky_insn_fpu.md: Refactor. Separate all float patterns + into emit-patterns and match-patterns, remain the emit-patterns here, + and move the match-patterns to csky_insn_fpuv2.md or + csky_insn_fpuv3.md. + * config/csky/csky_insn_fpuv2.md: New file for fpuv2 instructions. + * config/csky/csky_insn_fpuv3.md: New file and new patterns for fpuv3 + isntructions. + * config/csky/csky_isa.def (fcr): New. + (fpv3_hi): New. + (fpv3_hf): New. + (fpv3_sf): New. + (fpv3_df): New. + (CK860): New definition for ck860. + * config/csky/csky_tables.opt (ck860): New processors ck860, + ck860f. And new arch ck860. + (fpv3_hf): New. + (fpv3_hsf): New. + (fpv3_hdf): New. + (fpv3): New. + * config/csky/predicates.md (csky_float_comparsion_operator): Delete + "geu", "gtu", "leu", "ltu", which will never appear at float comparison. + * config/csky/t-csky-elf: Support 860. + * config/csky/t-csky-linux: Likewise. + * doc/md.texi: Add "Q" and "W" constraints for C-SKY. + 2021-05-24 Aaron Sawdey <acsawdey@linux.ibm.com> * config/rs6000/genfusion.pl (gen_logical_addsubf): Refactor to diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index e64bfab..f3c7e4f 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20210525 +20210526 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 1164554..da2ef24 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -3314,7 +3314,7 @@ TEXI_GCCINT_FILES = gccint.texi gcc-common.texi gcc-vers.texi \ loop.texi generic.texi gimple.texi plugins.texi optinfo.texi \ match-and-simplify.texi analyzer.texi ux.texi poly-int.texi -TEXI_GCCINSTALL_FILES = install.texi install-old.texi fdl.texi \ +TEXI_GCCINSTALL_FILES = install.texi fdl.texi \ gcc-common.texi gcc-vers.texi TEXI_CPPINT_FILES = cppinternals.texi gcc-common.texi gcc-vers.texi diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index b5ba177..14a8c58 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,7 @@ +2021-05-25 Martin Liska <mliska@suse.cz> + + * doc/share/conf.py: Fix Sphinx 4.0.x error. + 2021-05-21 Piotr Trojanek <trojanek@adacore.com> * gcc-interface/trans.c (Raise_Error_to_gnu): Add an assertion. diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 43d4c5e..28544c7 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,23 @@ +2021-05-25 Martin Liska <mliska@suse.cz> + + PR tree-optimization/92860 + PR target/99592 + * c-attribs.c (handle_optimize_attribute): Save target node + before calling parse_optimize_options and save it in case + it changes. + * c-pragma.c (handle_pragma_target): Similarly for pragma. + (handle_pragma_pop_options): Likewise here. + +2021-05-25 Martin Liska <mliska@suse.cz> + + * c-attribs.c (handle_no_sanitize_coverage_attribute): New. + +2021-05-25 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/99928 + * c-omp.c (c_omp_split_clauses): Copy reduction to teams when teams is + combined with simd and not with taskloop or for. + 2021-05-21 Jakub Jelinek <jakub@redhat.com> PR middle-end/99928 diff --git a/gcc/config/csky/constraints.md b/gcc/config/csky/constraints.md index c9bc9f2..2641ab3 100644 --- a/gcc/config/csky/constraints.md +++ b/gcc/config/csky/constraints.md @@ -38,6 +38,10 @@ "Memory operands with base register, index register" (match_test "csky_valid_mem_constraint_operand (op, \"W\")")) +(define_memory_constraint "Y" + "Memory operands without index register" + (not (match_test "csky_valid_mem_constraint_operand (op, \"W\")"))) + (define_constraint "R" "Memory operands whose address is a label_ref" (and (match_code "mem") diff --git a/gcc/config/csky/csky.c b/gcc/config/csky/csky.c index 7f2af82..c0e42a2 100644 --- a/gcc/config/csky/csky.c +++ b/gcc/config/csky/csky.c @@ -512,9 +512,6 @@ csky_cpu_cpp_builtins (cpp_reader *pfile) #undef TARGET_SPLIT_COMPLEX_ARG #define TARGET_SPLIT_COMPLEX_ARG hook_bool_const_tree_true -#undef TARGET_PROMOTE_PROTOTYPES -#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true - #undef TARGET_MUST_PASS_IN_STACK #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size @@ -3155,7 +3152,8 @@ ck810_legitimate_index_p (machine_mode mode, rtx index, int strict_p) /* The follow index is for ldr instruction, the ldr cannot load dword data, so the mode size should not be larger than 4. */ - else if (GET_MODE_SIZE (mode) <= 4) + else if (GET_MODE_SIZE (mode) <= 4 + || (TARGET_HARD_FLOAT && CSKY_VREG_MODE_P (mode))) { if (is_csky_address_register_rtx_p (index, strict_p)) return 1; diff --git a/gcc/config/csky/csky.md b/gcc/config/csky/csky.md index c27d627..f91d851 100644 --- a/gcc/config/csky/csky.md +++ b/gcc/config/csky/csky.md @@ -1533,6 +1533,7 @@ }" ) +;; hi -> si (define_insn "extendhisi2" [(set (match_operand:SI 0 "register_operand" "=r") (sign_extend:SI (match_operand:HI 1 "register_operand" "r")))] @@ -1557,6 +1558,15 @@ "sextb %0, %1" ) +(define_insn "*cskyv2_sextend_ldbs" + [(set (match_operand:SI 0 "register_operand" "=r") + (sign_extend:SI (match_operand:QI 1 "csky_simple_mem_operand" "m")))] + "CSKY_ISA_FEATURE (E2)" + "ld.bs\t%0, %1" + [(set_attr "length" "4") + (set_attr "type" "load")] +) + ;; qi -> hi (define_insn "extendqihi2" [(set (match_operand:HI 0 "register_operand" "=r") @@ -3248,6 +3258,10 @@ emit_call_insn (gen_call (operands[0], const0_rtx)); + for (int i = 0; i < XVECLEN (operands[2], 0); i++) + emit_clobber (SET_SRC (XVECEXP (operands[2], 0, i))); + emit_insn (gen_blockage ()); + for (i = 0; i < XVECLEN (operands[2], 0); i++) { rtx set = XVECEXP (operands[2], 0, i); diff --git a/gcc/config/csky/csky_insn_fpuv2.md b/gcc/config/csky/csky_insn_fpuv2.md index d56b61f..7bab99e 100644 --- a/gcc/config/csky/csky_insn_fpuv2.md +++ b/gcc/config/csky/csky_insn_fpuv2.md @@ -480,8 +480,8 @@ ) (define_insn "*fpuv2_movdf" - [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r, r,m, v,?r,Q,v,v,v") - (match_operand:DF 1 "general_operand" " r,m,mF,r,?r, v,v,Q,v,m"))] + [(set (match_operand:DF 0 "nonimmediate_operand" "=r, v,?r,Q,v,v,v,r, r,Y") + (match_operand:DF 1 "general_operand" " r,?r, v,v,Q,v,m,Y,YF,r"))] "CSKY_ISA_FEATURE (fpv2_df)" "* return csky_output_movedouble(operands, DFmode);" [(set (attr "length") diff --git a/gcc/config/csky/csky_insn_fpuv3.md b/gcc/config/csky/csky_insn_fpuv3.md index b5f4798..7b9d4a7 100644 --- a/gcc/config/csky/csky_insn_fpuv3.md +++ b/gcc/config/csky/csky_insn_fpuv3.md @@ -90,27 +90,27 @@ ) (define_insn "*fpv3_movdf" - [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r, r,m,v,?r,Q,v,v,v, v") - (match_operand:DF 1 "general_operand" " r,m,mF,r,?r,v,v,Q,v,m,Dv"))] + [(set (match_operand:DF 0 "nonimmediate_operand" "=r, v,?r,Q,v,v,v, v,r, r,Y") + (match_operand:DF 1 "general_operand" " r,?r, v,v,Q,v,m,Dv,Y,YF,r"))] "CSKY_ISA_FEATURE(fpv3_df)" "* switch (which_alternative) { - case 4: + case 1: if (TARGET_BIG_ENDIAN) return \"fmtvr.64\\t%0, %R1, %1\"; return \"fmtvr.64\\t%0, %1, %R1\"; - case 5: + case 2: if (TARGET_BIG_ENDIAN) return \"fmfvr.64\\t%R0, %0, %1\"; return \"fmfvr.64\\t%0, %R0, %1\"; + case 3: + case 4: case 6: - case 7: - case 9: return fpuv3_output_move(operands); - case 8: + case 5: return \"fmov.64\\t%0, %1\"; - case 10: + case 7: return \"fmovi.64\\t%0, %1\"; default: return csky_output_movedouble(operands, DFmode); diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h index f3e8572..f47d5b4 100644 --- a/gcc/config/riscv/riscv.h +++ b/gcc/config/riscv/riscv.h @@ -98,6 +98,7 @@ extern const char *riscv_default_mtune (int argc, const char **argv); %{" FPIE_OR_FPIC_SPEC ":-fpic} \ %{march=*} \ %{mabi=*} \ +%{mno-relax} \ %{mbig-endian} \ %{mlittle-endian} \ %(subtarget_asm_spec)" \ diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 2eb793e..1cbd043 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2021-05-25 Jakub Jelinek <jakub@redhat.com> + + PR c++/100666 + * call.c (convert_arg_to_ellipsis): For expressions with NULLPTR_TYPE + and side-effects, temporarily disable -Wunused-result warning when + building COMPOUND_EXPR. + 2021-05-21 Jakub Jelinek <jakub@redhat.com> PR middle-end/99928 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index cfccf27..3076fe6 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -8178,7 +8178,10 @@ convert_arg_to_ellipsis (tree arg, tsubst_flags_t complain) { arg = mark_rvalue_use (arg); if (TREE_SIDE_EFFECTS (arg)) - arg = cp_build_compound_expr (arg, null_pointer_node, complain); + { + warning_sentinel w(warn_unused_result); + arg = cp_build_compound_expr (arg, null_pointer_node, complain); + } else arg = null_pointer_node; } diff --git a/gcc/doc/install-old.texi b/gcc/doc/install-old.texi deleted file mode 100644 index 419e38d..0000000 --- a/gcc/doc/install-old.texi +++ /dev/null @@ -1,184 +0,0 @@ -@c Copyright (C) 1988-2021 Free Software Foundation, Inc. -@c This is part of the GCC manual. -@c For copying conditions, see the file install.texi. - -@ifnothtml -@comment node-name, next, previous, up -@node Old -@end ifnothtml -@html -<h1 align="center">Old installation documentation</h1> -@end html -@ifnothtml -@chapter Old installation documentation -@end ifnothtml - -Note most of this information is out of date and superseded by the -previous chapters of this manual. It is provided for historical -reference only, because of a lack of volunteers to merge it into the -main manual. - -@ifnothtml -@menu -* Configurations:: Configurations Supported by GCC. -@end menu -@end ifnothtml - -Here is the procedure for installing GCC on a GNU or Unix system. - -@enumerate -@item -If you have chosen a configuration for GCC which requires other GNU -tools (such as GAS or the GNU linker) instead of the standard system -tools, install the required tools in the build directory under the names -@file{as}, @file{ld} or whatever is appropriate. - -Alternatively, you can do subsequent compilation using a value of the -@code{PATH} environment variable such that the necessary GNU tools come -before the standard system tools. - -@item -Specify the host, build and target machine configurations. You do this -when you run the @file{configure} script. - -The @dfn{build} machine is the system which you are using, the -@dfn{host} machine is the system where you want to run the resulting -compiler (normally the build machine), and the @dfn{target} machine is -the system for which you want the compiler to generate code. - -If you are building a compiler to produce code for the machine it runs -on (a native compiler), you normally do not need to specify any operands -to @file{configure}; it will try to guess the type of machine you are on -and use that as the build, host and target machines. So you don't need -to specify a configuration when building a native compiler unless -@file{configure} cannot figure out what your configuration is or guesses -wrong. - -In those cases, specify the build machine's @dfn{configuration name} -with the @option{--host} option; the host and target will default to be -the same as the host machine. - -Here is an example: - -@smallexample -./configure --host=sparc-sun-sunos4.1 -@end smallexample - -A configuration name may be canonical or it may be more or less -abbreviated. - -A canonical configuration name has three parts, separated by dashes. -It looks like this: @samp{@var{cpu}-@var{company}-@var{system}}. -(The three parts may themselves contain dashes; @file{configure} -can figure out which dashes serve which purpose.) For example, -@samp{m68k-sun-sunos4.1} specifies a Sun 3. - -You can also replace parts of the configuration by nicknames or aliases. -For example, @samp{sun3} stands for @samp{m68k-sun}, so -@samp{sun3-sunos4.1} is another way to specify a Sun 3. - -You can specify a version number after any of the system types, and some -of the CPU types. In most cases, the version is irrelevant, and will be -ignored. So you might as well specify the version if you know it. - -See @ref{Configurations}, for a list of supported configuration names and -notes on many of the configurations. You should check the notes in that -section before proceeding any further with the installation of GCC@. - -@end enumerate - -@ifnothtml -@node Configurations, , , Old -@section Configurations Supported by GCC -@end ifnothtml -@html -<h2>@anchor{Configurations}Configurations Supported by GCC</h2> -@end html -@cindex configurations supported by GCC - -Here are the possible CPU types: - -@quotation -@c gmicro, fx80, spur and tahoe omitted since they don't work. -1750a, a29k, alpha, arm, avr, c@var{n}, clipper, dsp16xx, elxsi, fr30, h8300, -hppa1.0, hppa1.1, i370, i386, i486, i586, i686, i786, i860, i960, ip2k, m32r, -m68000, m68k, m88k, mcore, mips, mipsel, mips64, mips64el, -mn10200, mn10300, ns32k, pdp11, powerpc, powerpcle, romp, rs6000, sh, sparc, -sparclite, sparc64, v850, vax, we32k. -@end quotation - -Here are the recognized company names. As you can see, customary -abbreviations are used rather than the longer official names. - -@c What should be done about merlin, tek*, dolphin? -@quotation -acorn, alliant, altos, apollo, apple, att, bull, -cbm, convergent, convex, crds, dec, dg, dolphin, -elxsi, encore, harris, hitachi, hp, ibm, intergraph, isi, -mips, motorola, ncr, next, ns, omron, plexus, -sequent, sgi, sony, sun, tti, unicom, wrs. -@end quotation - -The company name is meaningful only to disambiguate when the rest of -the information supplied is insufficient. You can omit it, writing -just @samp{@var{cpu}-@var{system}}, if it is not needed. For example, -@samp{vax-ultrix4.2} is equivalent to @samp{vax-dec-ultrix4.2}. - -Here is a list of system types: - -@quotation -386bsd, aix, acis, amigaos, aos, aout, aux, bosx, bsd, clix, coff, ctix, cxux, -dgux, dynix, ebmon, ecoff, elf, esix, freebsd, hms, genix, gnu, linux, -linux-gnu, hiux, hpux, iris, irix, isc, luna, lynxos, mach, minix, msdos, mvs, -netbsd, newsos, nindy, ns, osf, osfrose, ptx, riscix, riscos, rtu, sco, sim, -solaris, sunos, sym, sysv, udi, ultrix, unicos, uniplus, unos, vms, vsta, -vxworks, winnt, xenix. -@end quotation - -@noindent -You can omit the system type; then @file{configure} guesses the -operating system from the CPU and company. - -You can add a version number to the system type; this may or may not -make a difference. For example, you can write @samp{bsd4.3} or -@samp{bsd4.4} to distinguish versions of BSD@. In practice, the version -number is most needed for @samp{sysv3} and @samp{sysv4}, which are often -treated differently. - -@samp{linux-gnu} is the canonical name for the GNU/Linux target; however -GCC will also accept @samp{linux}. The version of the kernel in use is -not relevant on these systems. A suffix such as @samp{libc1} or @samp{aout} -distinguishes major versions of the C library; all of the suffixed versions -are obsolete. - -If you specify an impossible combination such as @samp{i860-dg-vms}, -then you may get an error message from @file{configure}, or it may -ignore part of the information and do the best it can with the rest. -@file{configure} always prints the canonical name for the alternative -that it used. GCC does not support all possible alternatives. - -Often a particular model of machine has a name. Many machine names are -recognized as aliases for CPU/company combinations. Thus, the machine -name @samp{sun3}, mentioned above, is an alias for @samp{m68k-sun}. -Sometimes we accept a company name as a machine name, when the name is -popularly used for a particular machine. Here is a table of the known -machine names: - -@quotation -3300, 3b1, 3b@var{n}, 7300, altos3068, altos, -apollo68, att-7300, balance, -convex-c@var{n}, crds, decstation-3100, -decstation, delta, encore, -fx2800, gmicro, hp7@var{nn}, hp8@var{nn}, -hp9k2@var{nn}, hp9k3@var{nn}, hp9k7@var{nn}, -hp9k8@var{nn}, iris4d, iris, isi68, -m3230, magnum, merlin, miniframe, -mmax, news-3600, news800, news, next, -pbd, pc532, pmax, powerpc, powerpcle, ps2, risc-news, -rtpc, sun2, sun386i, sun386, sun3, -sun4, symmetry, tower-32, tower. -@end quotation - -@noindent -Remember that a machine name specifies both the cpu type and the company -name. diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi index e294494..4066347 100644 --- a/gcc/doc/install.texi +++ b/gcc/doc/install.texi @@ -36,9 +36,6 @@ @ifset binarieshtml @settitle Installing GCC: Binaries @end ifset -@ifset oldhtml -@settitle Installing GCC: Old documentation -@end ifset @ifset gfdlhtml @settitle Installing GCC: GNU Free Documentation License @end ifset @@ -62,7 +59,6 @@ @set testhtml @set finalinstallhtml @set binarieshtml -@set oldhtml @set gfdlhtml @end ifnothtml @@ -122,8 +118,6 @@ Free Documentation License}''. * Specific:: Host/target specific installation notes for GCC. * Binaries:: Where to get pre-compiled binaries. -* Old:: Old installation documentation. - * GNU Free Documentation License:: How you can copy and share this manual. * Concept Index:: This index has two entries. @end menu @@ -705,23 +699,67 @@ The default value is @uref{https://gcc.gnu.org/,,https://gcc.gnu.org/}. @end table -@heading Target specification -@itemize @bullet -@item -GCC has code to correctly determine the correct value for @var{target} -for nearly all native systems. Therefore, we highly recommend you do -not provide a configure target when configuring a native compiler. +@heading Host, Build and Target specification -@item -@var{target} must be specified as @option{--target=@var{target}} -when configuring a cross compiler; examples of valid targets would be -m68k-elf, sh-elf, etc. +Specify the host, build and target machine configurations. You do this +when you run the @file{configure} script. -@item -Specifying just @var{target} instead of @option{--target=@var{target}} -implies that the host defaults to @var{target}. -@end itemize +The @dfn{build} machine is the system which you are using, the +@dfn{host} machine is the system where you want to run the resulting +compiler (normally the build machine), and the @dfn{target} machine is +the system for which you want the compiler to generate code. + +If you are building a compiler to produce code for the machine it runs +on (a native compiler), you normally do not need to specify any operands +to @file{configure}; it will try to guess the type of machine you are on +and use that as the build, host and target machines. So you don't need +to specify a configuration when building a native compiler unless +@file{configure} cannot figure out what your configuration is or guesses +wrong. + +In those cases, specify the build machine's @dfn{configuration name} +with the @option{--host} option; the host and target will default to be +the same as the host machine. + +Here is an example: + +@smallexample +./configure --host=x86_64-pc-linux-gnu +@end smallexample +A configuration name may be canonical or it may be more or less +abbreviated (@file{config.sub} script produces canonical versions). + +A canonical configuration name has three parts, separated by dashes. +It looks like this: @samp{@var{cpu}-@var{company}-@var{system}}. + +Here are the possible CPU types: + +@quotation +aarch64, aarch64_be, alpha, alpha64, amdgcn, arc, arceb, arm, armeb, avr, bfin, +bpf, cr16, cris, csky, epiphany, fido, fr30, frv, ft32, h8300, hppa, hppa2.0, +hppa64, i486, i686, ia64, iq2000, lm32, m32c, m32r, m32rle, m68k, mcore, +microblaze, microblazeel, mips, mips64, mips64el, mips64octeon, mips64orion, +mips64vr, mipsel, mipsisa32, mipsisa32r2, mipsisa64, mipsisa64r2, +mipsisa64r2el, mipsisa64sb1, mipsisa64sr71k, mipstx39, mmix, mn10300, moxie, +msp430, nds32be, nds32le, nios2, nvptx, or1k, pdp11, powerpc, powerpc64, +powerpc64le, powerpcle, pru, riscv32, riscv32be, riscv64, riscv64be, rl78, rx, +s390, s390x, sh, shle, sparc, sparc64, tic6x, tilegx, tilegxbe, tilepro, v850, +v850e, v850e1, vax, visium, x86_64, xstormy16, xtensa +@end quotation + +Here is a list of system types: + +@quotation +aix@var{version}, amdhsa, aout, cygwin, darwin@var{version}, +eabi, eabialtivec, eabisim, eabisimaltivec, elf, elf32, +elfbare, elfoabi, freebsd@var{version}, gnu, hpux, hpux@var{version}, +kfreebsd-gnu, kopensolaris-gnu, linux-androideabi, linux-gnu, +linux-gnu_altivec, linux-musl, linux-uclibc, lynxos, mingw32, mingw32crt, +mmixware, msdosdjgpp, netbsd, netbsdelf@var{version}, nto-qnx, openbsd, +rtems, solaris@var{version}, symbianelf, tpf, uclinux, uclinux_eabi, vms, +vxworks, vxworksae, vxworksmils +@end quotation @heading Options specification @@ -5142,18 +5180,6 @@ automatically. @end ifhtml @end ifset -@c ***Old documentation****************************************************** -@ifset oldhtml -@include install-old.texi -@html -<hr /> -<p> -@end html -@ifhtml -@uref{./index.html,,Return to the GCC Installation page} -@end ifhtml -@end ifset - @c ***GFDL******************************************************************** @ifset gfdlhtml @include fdl.texi diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index e614039..b30db1c 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,9 @@ +2021-05-25 Tobias Burnus <tobias@codesourcery.com> + Johannes Nendwich <a08727063@unet.univie.ac.at> + + * intrinsic.texi (GERROR, GETARGS, GETLOG, NORM2, PARITY, RANDOM_INIT, + RANDOM_NUMBER): Fix typos and copy'n'paste errors. + 2021-05-24 Tobias Burnus <tobias@codesourcery.com> PR fortran/86470 diff --git a/gcc/gimple-range-cache.cc b/gcc/gimple-range-cache.cc index 2c922e3..3969c4d 100644 --- a/gcc/gimple-range-cache.cc +++ b/gcc/gimple-range-cache.cc @@ -474,43 +474,28 @@ ssa_global_cache::dump (FILE *f) // -------------------------------------------------------------------------- -// This struct provides a timestamp for a global range calculation. -// it contains the time counter, as well as a limited number of ssa-names -// that it is dependent upon. If the timestamp for any of the dependent names -// Are newer, then this range could need updating. - -struct range_timestamp -{ - unsigned time; - unsigned ssa1; - unsigned ssa2; -}; - // This class will manage the timestamps for each ssa_name. -// When a value is calcualted, its timestamp is set to the current time. -// The ssanames it is dependent on have already been calculated, so they will -// have older times. If one fo those values is ever calculated again, it -// will get a newer timestamp, and the "current_p" check will fail. +// When a value is calculated, the timestamp is set to the current time. +// Current time is then incremented. Any dependencies will already have +// been calculated, and will thus have older timestamps. +// If one of those values is ever calculated again, it will get a newer +// timestamp, and the "current_p" check will fail. class temporal_cache { public: temporal_cache (); ~temporal_cache (); - bool current_p (tree name) const; + bool current_p (tree name, tree dep1, tree dep2) const; void set_timestamp (tree name); - void set_dependency (tree name, tree dep); void set_always_current (tree name); private: unsigned temporal_value (unsigned ssa) const; - const range_timestamp *get_timestamp (unsigned ssa) const; - range_timestamp *get_timestamp (unsigned ssa); unsigned m_current_time; - vec <range_timestamp> m_timestamp; + vec <unsigned> m_timestamp; }; - inline temporal_cache::temporal_cache () { @@ -525,65 +510,35 @@ temporal_cache::~temporal_cache () m_timestamp.release (); } -// Return a pointer to the timetamp for ssa-name at index SSA, if there is -// one, otherwise return NULL. - -inline const range_timestamp * -temporal_cache::get_timestamp (unsigned ssa) const -{ - if (ssa >= m_timestamp.length ()) - return NULL; - return &(m_timestamp[ssa]); -} - -// Return a reference to the timetamp for ssa-name at index SSA. If the index -// is past the end of the vector, extend the vector. - -inline range_timestamp * -temporal_cache::get_timestamp (unsigned ssa) -{ - if (ssa >= m_timestamp.length ()) - m_timestamp.safe_grow_cleared (num_ssa_names + 20); - return &(m_timestamp[ssa]); -} - -// This routine will fill NAME's next operand slot with DEP if DEP is a valid -// SSA_NAME and there is a free slot. - -inline void -temporal_cache::set_dependency (tree name, tree dep) -{ - if (dep && TREE_CODE (dep) == SSA_NAME) - { - gcc_checking_assert (get_timestamp (SSA_NAME_VERSION (name))); - range_timestamp& ts = *(get_timestamp (SSA_NAME_VERSION (name))); - if (!ts.ssa1) - ts.ssa1 = SSA_NAME_VERSION (dep); - else if (!ts.ssa2 && ts.ssa1 != SSA_NAME_VERSION (name)) - ts.ssa2 = SSA_NAME_VERSION (dep); - } -} - // Return the timestamp value for SSA, or 0 if there isnt one. + inline unsigned temporal_cache::temporal_value (unsigned ssa) const { - const range_timestamp *ts = get_timestamp (ssa); - return ts ? ts->time : 0; + if (ssa >= m_timestamp.length ()) + return 0; + return m_timestamp[ssa]; } // Return TRUE if the timestampe for NAME is newer than any of its dependents. +// Up to 2 dependencies can be checked. bool -temporal_cache::current_p (tree name) const +temporal_cache::current_p (tree name, tree dep1, tree dep2) const { - const range_timestamp *ts = get_timestamp (SSA_NAME_VERSION (name)); - if (!ts || ts->time == 0) + unsigned ts = temporal_value (SSA_NAME_VERSION (name)); + if (ts == 0) return true; + // Any non-registered dependencies will have a value of 0 and thus be older. // Return true if time is newer than either dependent. - return ts->time > temporal_value (ts->ssa1) - && ts->time > temporal_value (ts->ssa2); + + if (dep1 && ts < temporal_value (SSA_NAME_VERSION (dep1))) + return false; + if (dep2 && ts < temporal_value (SSA_NAME_VERSION (dep2))) + return false; + + return true; } // This increments the global timer and sets the timestamp for NAME. @@ -591,8 +546,10 @@ temporal_cache::current_p (tree name) const inline void temporal_cache::set_timestamp (tree name) { - gcc_checking_assert (get_timestamp (SSA_NAME_VERSION (name))); - get_timestamp (SSA_NAME_VERSION (name))->time = ++m_current_time; + unsigned v = SSA_NAME_VERSION (name); + if (v >= m_timestamp.length ()) + m_timestamp.safe_grow_cleared (num_ssa_names + 20); + m_timestamp[v] = ++m_current_time; } // Set the timestamp to 0, marking it as "always up to date". @@ -600,11 +557,12 @@ temporal_cache::set_timestamp (tree name) inline void temporal_cache::set_always_current (tree name) { - gcc_checking_assert (get_timestamp (SSA_NAME_VERSION (name))); - get_timestamp (SSA_NAME_VERSION (name))->time = 0; + unsigned v = SSA_NAME_VERSION (name); + if (v >= m_timestamp.length ()) + m_timestamp.safe_grow_cleared (num_ssa_names + 20); + m_timestamp[v] = 0; } - // -------------------------------------------------------------------------- ranger_cache::ranger_cache (gimple_ranger &q) : query (q) @@ -618,6 +576,16 @@ ranger_cache::ranger_cache (gimple_ranger &q) : query (q) m_poor_value_list.safe_grow_cleared (20); m_poor_value_list.truncate (0); m_temporal = new temporal_cache; + unsigned x, lim = last_basic_block_for_fn (cfun); + // Calculate outgoing range info upfront. This will fully populate the + // m_maybe_variant bitmap which will help eliminate processing of names + // which never have their ranges adjusted. + for (x = 0; x < lim ; x++) + { + basic_block bb = BASIC_BLOCK_FOR_FN (cfun, x); + if (bb) + exports (bb); + } } ranger_cache::~ranger_cache () @@ -672,7 +640,7 @@ ranger_cache::get_non_stale_global_range (irange &r, tree name) { if (m_globals.get_global_range (r, name)) { - if (m_temporal->current_p (name)) + if (m_temporal->current_p (name, depend1 (name), depend2 (name))) return true; } else @@ -718,16 +686,6 @@ ranger_cache::set_global_range (tree name, const irange &r) m_temporal->set_timestamp (name); } -// Register a dependency on DEP to name. If the timestamp for DEP is ever -// greateer than the timestamp for NAME, then it is newer and NAMEs value -// becomes stale. - -void -ranger_cache::register_dependency (tree name, tree dep) -{ - m_temporal->set_dependency (name, dep); -} - // Push a request for a new lookup in block BB of name. Return true if // the request is actually made (ie, isn't a duplicate). diff --git a/gcc/gimple-range-cache.h b/gcc/gimple-range-cache.h index 15e6d0c..fe781e0 100644 --- a/gcc/gimple-range-cache.h +++ b/gcc/gimple-range-cache.h @@ -98,7 +98,6 @@ public: bool get_global_range (irange &r, tree name) const; bool get_non_stale_global_range (irange &r, tree name); void set_global_range (tree name, const irange &r); - void register_dependency (tree name, tree dep); non_null_ref m_non_null; diff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc index 420282d..a4c4bf5 100644 --- a/gcc/gimple-range-gori.cc +++ b/gcc/gimple-range-gori.cc @@ -56,7 +56,7 @@ is_gimple_logical_p (const gimple *gs) return false; } -/* RANGE_DEF_CHAIN is used to determine what SSA names in a block can +/* RANGE_DEF_CHAIN is used to determine which SSA names in a block can have range information calculated for them, and what the dependencies on each other are. @@ -91,25 +91,11 @@ is_gimple_logical_p (const gimple *gs) engine implements operations for. */ -class range_def_chain -{ -public: - range_def_chain (); - ~range_def_chain (); - bool has_def_chain (tree name); - bitmap get_def_chain (tree name); - bool in_chain_p (tree name, tree def); -private: - vec<bitmap> m_def_chain; // SSA_NAME : def chain components. - void build_def_chain (tree name, bitmap result, basic_block bb); - int m_logical_depth; -}; - - // Construct a range_def_chain. range_def_chain::range_def_chain () { + bitmap_obstack_initialize (&m_bitmaps); m_def_chain.create (0); m_def_chain.safe_grow_cleared (num_ssa_names); m_logical_depth = 0; @@ -119,11 +105,8 @@ range_def_chain::range_def_chain () range_def_chain::~range_def_chain () { - unsigned x; - for (x = 0; x < m_def_chain.length (); ++x) - if (m_def_chain[x]) - BITMAP_FREE (m_def_chain[x]); m_def_chain.release (); + bitmap_obstack_release (&m_bitmaps); } // Return true if NAME is in the def chain of DEF. If BB is provided, @@ -143,26 +126,112 @@ range_def_chain::in_chain_p (tree name, tree def) return bitmap_bit_p (chain, SSA_NAME_VERSION (name)); } +// Add either IMP or the import list B to the import set of DATA. + +void +range_def_chain::set_import (struct rdc &data, tree imp, bitmap b) +{ + // If there are no imports, just return + if (imp == NULL_TREE && !b) + return; + if (!data.m_import) + data.m_import = BITMAP_ALLOC (&m_bitmaps); + if (imp != NULL_TREE) + bitmap_set_bit (data.m_import, SSA_NAME_VERSION (imp)); + else + bitmap_ior_into (data.m_import, b); +} + +// Return the import list for NAME. + +bitmap +range_def_chain::get_imports (tree name) +{ + if (!has_def_chain (name)) + get_def_chain (name); + bitmap i = m_def_chain[SSA_NAME_VERSION (name)].m_import; + // Either this is a default def, OR imports must be a subset of exports. + gcc_checking_assert (!get_def_chain (name) || !i + || !bitmap_intersect_compl_p (i, get_def_chain (name))); + return i; +} + +// Return true if IMPORT is an import to NAMEs def chain. + +bool +range_def_chain::chain_import_p (tree name, tree import) +{ + bitmap b = get_imports (name); + if (b) + return bitmap_bit_p (b, SSA_NAME_VERSION (import)); + return false; +} + // Build def_chains for NAME if it is in BB. Copy the def chain into RESULT. void -range_def_chain::build_def_chain (tree name, bitmap result, basic_block bb) +range_def_chain::register_dependency (tree name, tree dep, basic_block bb) { + if (!gimple_range_ssa_p (dep)) + return; + + unsigned v = SSA_NAME_VERSION (name); + struct rdc &src = m_def_chain[v]; + gimple *def_stmt = SSA_NAME_DEF_STMT (dep); + unsigned dep_v = SSA_NAME_VERSION (dep); bitmap b; - gimple *def_stmt = SSA_NAME_DEF_STMT (name); + + // Set the direct dependency cache entries. + if (!src.ssa1) + src.ssa1 = dep; + else if (!src.ssa2 && src.ssa1 != dep) + src.ssa2 = dep; + + // Don't calculate imports or export/dep chains if BB is not provided. + // This is usually the case for when the temporal cache wants the direct + // dependencies of a stmt. + if (!bb) + return; + + if (!src.bm) + src.bm = BITMAP_ALLOC (&m_bitmaps); + // Add this operand into the result. - bitmap_set_bit (result, SSA_NAME_VERSION (name)); + bitmap_set_bit (src.bm, dep_v); if (gimple_bb (def_stmt) == bb && !is_a<gphi *>(def_stmt)) { // Get the def chain for the operand. - b = get_def_chain (name); + b = get_def_chain (dep); // If there was one, copy it into result. if (b) - bitmap_ior_into (result, b); + bitmap_ior_into (src.bm, b); + // And copy the import list. + set_import (src, NULL_TREE, get_imports (dep)); } + else + // Originated outside the block, so it is an import. + set_import (src, dep, NULL); } +bool +range_def_chain::def_chain_in_bitmap_p (tree name, bitmap b) +{ + bitmap a = get_def_chain (name); + if (a && b) + return bitmap_intersect_p (a, b); + return false; +} + +void +range_def_chain::add_def_chain_to_bitmap (bitmap b, tree name) +{ + bitmap r = get_def_chain (name); + if (r) + bitmap_ior_into (b, r); +} + + // Return TRUE if NAME has been processed for a def_chain. inline bool @@ -172,9 +241,11 @@ range_def_chain::has_def_chain (tree name) unsigned v = SSA_NAME_VERSION (name); if (v >= m_def_chain.length ()) m_def_chain.safe_grow_cleared (num_ssa_names + 1); - return (m_def_chain[v] != NULL); + return (m_def_chain[v].ssa1 != 0); } + + // Calculate the def chain for NAME and all of its dependent // operands. Only using names in the same BB. Return the bitmap of // all names in the m_def_chain. This only works for supported range @@ -189,11 +260,15 @@ range_def_chain::get_def_chain (tree name) // If it has already been processed, just return the cached value. if (has_def_chain (name)) - return m_def_chain[v]; + return m_def_chain[v].bm; // No definition chain for default defs. if (SSA_NAME_IS_DEFAULT_DEF (name)) - return NULL; + { + // A Default def is always an import. + set_import (m_def_chain[v], name, NULL); + return NULL; + } gimple *stmt = SSA_NAME_DEF_STMT (name); if (gimple_range_handler (stmt)) @@ -220,30 +295,63 @@ range_def_chain::get_def_chain (tree name) ssa3 = gimple_range_ssa_p (gimple_assign_rhs3 (st)); } else - return NULL; - - basic_block bb = gimple_bb (stmt); - - m_def_chain[v] = BITMAP_ALLOC (NULL); + { + // Stmts not understood are always imports. + set_import (m_def_chain[v], name, NULL); + return NULL; + } - if (ssa1) - build_def_chain (ssa1, m_def_chain[v], bb); - if (ssa2) - build_def_chain (ssa2, m_def_chain[v], bb); - if (ssa3) - build_def_chain (ssa3, m_def_chain[v], bb); + register_dependency (name, ssa1, gimple_bb (stmt)); + register_dependency (name, ssa2, gimple_bb (stmt)); + register_dependency (name, ssa3, gimple_bb (stmt)); + // Stmts with no understandable operands are also imports. + if (!ssa1 && !ssa2 & !ssa3) + set_import (m_def_chain[v], name, NULL); if (is_logical) m_logical_depth--; - // If we run into pathological cases where the defintion chains are - // huge (ie huge basic block fully unrolled) we might be able to limit - // this by deciding here that if some criteria is satisfied, we change the - // def_chain back to be just the ssa-names. That will help prevent chains - // of a_2 = b_6 + a_8 from creating a pathological case. - return m_def_chain[v]; + return m_def_chain[v].bm; } +// Dump what we know for basic block BB to file F. + +void +range_def_chain::dump (FILE *f, basic_block bb, const char *prefix) +{ + unsigned x, y; + bitmap_iterator bi; + + // Dump the def chain for each SSA_NAME defined in BB. + for (x = 1; x < num_ssa_names; x++) + { + tree name = ssa_name (x); + if (!name) + continue; + gimple *stmt = SSA_NAME_DEF_STMT (name); + if (!stmt || (bb && gimple_bb (stmt) != bb)) + continue; + bitmap chain = (has_def_chain (name) ? get_def_chain (name) : NULL); + if (chain && !bitmap_empty_p (chain)) + { + fprintf (f, prefix); + print_generic_expr (f, name, TDF_SLIM); + fprintf (f, " : "); + + bitmap imports = get_imports (name); + EXECUTE_IF_SET_IN_BITMAP (chain, 0, y, bi) + { + print_generic_expr (f, ssa_name (y), TDF_SLIM); + if (imports && bitmap_bit_p (imports, y)) + fprintf (f, "(I)"); + fprintf (f, " "); + } + fprintf (f, "\n"); + } + } +} + + // ------------------------------------------------------------------- /* GORI_MAP is used to accumulate what SSA names in a block can @@ -264,27 +372,6 @@ range_def_chain::get_def_chain (tree name) entire def_chain of all SSA names used in the last statement of the block which generate ranges. */ -class gori_map : public range_def_chain -{ -public: - gori_map (); - ~gori_map (); - - bool is_export_p (tree name, basic_block bb = NULL); - bool def_chain_in_export_p (tree name, basic_block bb); - bitmap exports (basic_block bb); - void set_range_invariant (tree name); - - void dump (FILE *f); - void dump (FILE *f, basic_block bb); -private: - bitmap_obstack m_bitmaps; - vec<bitmap> m_outgoing; // BB: Outgoing ranges calculatable on edges - bitmap m_maybe_variant; // Names which might have outgoing ranges. - void maybe_add_gori (tree name, basic_block bb); - void calculate_gori (basic_block bb); -}; - // Initialize a gori-map structure. @@ -292,7 +379,8 @@ gori_map::gori_map () { m_outgoing.create (0); m_outgoing.safe_grow_cleared (last_basic_block_for_fn (cfun)); - bitmap_obstack_initialize (&m_bitmaps); + m_incoming.create (0); + m_incoming.safe_grow_cleared (last_basic_block_for_fn (cfun)); m_maybe_variant = BITMAP_ALLOC (&m_bitmaps); } @@ -300,7 +388,7 @@ gori_map::gori_map () gori_map::~gori_map () { - bitmap_obstack_release (&m_bitmaps); + m_incoming.release (); m_outgoing.release (); } @@ -309,11 +397,21 @@ gori_map::~gori_map () bitmap gori_map::exports (basic_block bb) { - if (!m_outgoing[bb->index]) + if (bb->index >= (signed int)m_outgoing.length () || !m_outgoing[bb->index]) calculate_gori (bb); return m_outgoing[bb->index]; } +// Return the bitmap vector of all imports to BB. Calculate if necessary. + +bitmap +gori_map::imports (basic_block bb) +{ + if (bb->index >= (signed int)m_outgoing.length () || !m_outgoing[bb->index]) + calculate_gori (bb); + return m_incoming[bb->index]; +} + // Return true if NAME is can have ranges generated for it from basic // block BB. @@ -334,17 +432,13 @@ gori_map::set_range_invariant (tree name) bitmap_clear_bit (m_maybe_variant, SSA_NAME_VERSION (name)); } -// Return true if any element in the def chain of NAME is in the -// export list for BB. +// Return true if NAME is an import to block BB. bool -gori_map::def_chain_in_export_p (tree name, basic_block bb) +gori_map::is_import_p (tree name, basic_block bb) { - bitmap a = exports (bb); - bitmap b = get_def_chain (name); - if (a && b) - return bitmap_intersect_p (a, b); - return false; + // If no BB is specified, test if it is exported anywhere in the IL. + return bitmap_bit_p (imports (bb), SSA_NAME_VERSION (name)); } // If NAME is non-NULL and defined in block BB, calculate the def @@ -355,11 +449,17 @@ gori_map::maybe_add_gori (tree name, basic_block bb) { if (name) { - gimple *s = SSA_NAME_DEF_STMT (name); - bitmap r = get_def_chain (name); - // Check if there is a def chain, and it is in this block. - if (r && gimple_bb (s) == bb) - bitmap_copy (m_outgoing[bb->index], r); + // Check if there is a def chain, regardless of the block. + add_def_chain_to_bitmap (m_outgoing[bb->index], name); + // Check for any imports. + bitmap imp = get_imports (name); + // If there were imports, add them so we can recompute + if (imp) + bitmap_ior_into (m_incoming[bb->index], imp); + // This name is always an import. + if (gimple_bb (SSA_NAME_DEF_STMT (name)) != bb) + bitmap_set_bit (m_incoming[bb->index], SSA_NAME_VERSION (name)); + // Def chain doesn't include itself, and even if there isn't a // def chain, this name should be added to exports. bitmap_set_bit (m_outgoing[bb->index], SSA_NAME_VERSION (name)); @@ -373,9 +473,13 @@ gori_map::calculate_gori (basic_block bb) { tree name; if (bb->index >= (signed int)m_outgoing.length ()) - m_outgoing.safe_grow_cleared (last_basic_block_for_fn (cfun)); + { + m_outgoing.safe_grow_cleared (last_basic_block_for_fn (cfun)); + m_incoming.safe_grow_cleared (last_basic_block_for_fn (cfun)); + } gcc_checking_assert (m_outgoing[bb->index] == NULL); m_outgoing[bb->index] = BITMAP_ALLOC (&m_bitmaps); + m_incoming[bb->index] = BITMAP_ALLOC (&m_bitmaps); // If this block's last statement may generate range informaiton, go // calculate it. @@ -404,65 +508,42 @@ gori_map::calculate_gori (basic_block bb) // Dump the table information for BB to file F. void -gori_map::dump (FILE *f, basic_block bb) +gori_map::dump (FILE *f, basic_block bb, bool verbose) { - bool header = false; - const char *header_string = "bb%-4d "; - const char *header2 = " "; - bool printed_something = false;; - unsigned x, y; - bitmap_iterator bi; - // BB was not processed. - if (!m_outgoing[bb->index]) + if (!m_outgoing[bb->index] || bitmap_empty_p (m_outgoing[bb->index])) return; - // Dump the def chain for each SSA_NAME defined in BB. - for (x = 1; x < num_ssa_names; x++) + tree name; + + bitmap imp = imports (bb); + if (!bitmap_empty_p (imp)) { - tree name = ssa_name (x); - if (!name) - continue; - gimple *stmt = SSA_NAME_DEF_STMT (name); - bitmap chain = (has_def_chain (name) ? get_def_chain (name) : NULL); - if (stmt && gimple_bb (stmt) == bb && chain && !bitmap_empty_p (chain)) - { - fprintf (f, header_string, bb->index); - header_string = header2; - header = true; + if (verbose) + fprintf (f, "bb<%u> Imports: ",bb->index); + else + fprintf (f, "Imports: "); + FOR_EACH_GORI_IMPORT_NAME (*this, bb, name) + { print_generic_expr (f, name, TDF_SLIM); - fprintf (f, " : "); - EXECUTE_IF_SET_IN_BITMAP (chain, 0, y, bi) - { - print_generic_expr (f, ssa_name (y), TDF_SLIM); - fprintf (f, " "); - } - fprintf (f, "\n"); + fprintf (f, " "); } + fputc ('\n', f); } - printed_something |= header; - - // Now dump the export vector. - header = false; - EXECUTE_IF_SET_IN_BITMAP (m_outgoing[bb->index], 0, y, bi) + if (verbose) + fprintf (f, "bb<%u> Exports: ",bb->index); + else + fprintf (f, "Exports: "); + // Dump the export vector. + FOR_EACH_GORI_EXPORT_NAME (*this, bb, name) { - if (!header) - { - fprintf (f, header_string, bb->index); - fprintf (f, "exports: "); - header_string = header2; - header = true; - } - print_generic_expr (f, ssa_name (y), TDF_SLIM); + print_generic_expr (f, name, TDF_SLIM); fprintf (f, " "); } - if (header) - fputc ('\n', f); + fputc ('\n', f); - printed_something |= header; - if (printed_something) - fprintf (f, "\n"); + range_def_chain::dump (f, bb, " "); } // Dump the entire GORI map structure to file F. @@ -472,11 +553,7 @@ gori_map::dump (FILE *f) { basic_block bb; FOR_EACH_BB_FN (bb, cfun) - { - dump (f, bb); - if (m_outgoing[bb->index]) - fprintf (f, "\n"); - } + dump (f, bb); } DEBUG_FUNCTION void @@ -494,24 +571,6 @@ gori_compute::gori_compute () // Create a boolean_type true and false range. m_bool_zero = int_range<2> (boolean_false_node, boolean_false_node); m_bool_one = int_range<2> (boolean_true_node, boolean_true_node); - m_gori_map = new gori_map; - unsigned x, lim = last_basic_block_for_fn (cfun); - // Calculate outgoing range info upfront. This will fully populate the - // m_maybe_variant bitmap which will help eliminate processing of names - // which never have their ranges adjusted. - for (x = 0; x < lim ; x++) - { - basic_block bb = BASIC_BLOCK_FOR_FN (cfun, x); - if (bb) - m_gori_map->exports (bb); - } -} - -// Destruct a gori_compute_object. - -gori_compute::~gori_compute () -{ - delete m_gori_map; } // Provide a default of VARYING for all incoming SSA names. @@ -523,10 +582,10 @@ gori_compute::ssa_range_in_bb (irange &r, tree name, basic_block) } void -gori_compute::expr_range_in_bb (irange &r, tree expr, basic_block bb) +gori_compute::expr_range_at_stmt (irange &r, tree expr, gimple *s) { if (gimple_range_ssa_p (expr)) - ssa_range_in_bb (r, expr, bb); + ssa_range_in_bb (r, expr, gimple_bb (s)); else get_tree_range (r, expr); } @@ -547,7 +606,7 @@ gori_compute::compute_name_range_op (irange &r, gimple *stmt, // Operand 1 is the name being looked for, evaluate it. if (op1 == name) { - expr_range_in_bb (op1_range, op1, gimple_bb (stmt)); + expr_range_at_stmt (op1_range, op1, stmt); if (!op2) { // The second parameter to a unary operation is the range @@ -557,7 +616,7 @@ gori_compute::compute_name_range_op (irange &r, gimple *stmt, return gimple_range_calc_op1 (r, stmt, lhs, op1_range); } // If we need the second operand, get a value and evaluate. - expr_range_in_bb (op2_range, op2, gimple_bb (stmt)); + expr_range_at_stmt (op2_range, op2, stmt); if (gimple_range_calc_op1 (r, stmt, lhs, op2_range)) r.intersect (op1_range); else @@ -567,8 +626,8 @@ gori_compute::compute_name_range_op (irange &r, gimple *stmt, if (op2 == name) { - expr_range_in_bb (op1_range, op1, gimple_bb (stmt)); - expr_range_in_bb (r, op2, gimple_bb (stmt)); + expr_range_at_stmt (op1_range, op1, stmt); + expr_range_at_stmt (r, op2, stmt); if (gimple_range_calc_op2 (op2_range, stmt, lhs, op1_range)) r.intersect (op2_range); return true; @@ -597,7 +656,7 @@ gori_compute::compute_operand_range_switch (irange &r, gswitch *s, } // If op1 is in the defintion chain, pass lhs back. - if (gimple_range_ssa_p (op1) && m_gori_map->in_chain_p (name, op1)) + if (gimple_range_ssa_p (op1) && in_chain_p (name, op1)) return compute_operand_range (r, SSA_NAME_DEF_STMT (op1), lhs, name); return false; @@ -635,8 +694,8 @@ gori_compute::compute_operand_range (irange &r, gimple *stmt, // NAME is not in this stmt, but one of the names in it ought to be // derived from it. - bool op1_in_chain = op1 && m_gori_map->in_chain_p (name, op1); - bool op2_in_chain = op2 && m_gori_map->in_chain_p (name, op2); + bool op1_in_chain = op1 && in_chain_p (name, op1); + bool op2_in_chain = op2 && in_chain_p (name, op2); if (op1_in_chain && op2_in_chain) return compute_operand1_and_operand2_range (r, stmt, lhs, name); if (op1_in_chain) @@ -818,7 +877,7 @@ gori_compute::optimize_logical_operands (tf_range &range, { if (!compute_operand_range (range.false_range, SSA_NAME_DEF_STMT (op), m_bool_zero, name)) - expr_range_in_bb (range.false_range, name, gimple_bb (stmt)); + expr_range_at_stmt (range.false_range, name, stmt); range.true_range = range.false_range; return true; } @@ -827,7 +886,7 @@ gori_compute::optimize_logical_operands (tf_range &range, { if (!compute_operand_range (range.true_range, SSA_NAME_DEF_STMT (op), m_bool_one, name)) - expr_range_in_bb (range.true_range, name, gimple_bb (stmt)); + expr_range_at_stmt (range.true_range, name, stmt); range.false_range = range.true_range; return true; } @@ -846,12 +905,12 @@ gori_compute::compute_logical_operands_in_chain (tf_range &range, tree op, bool op_in_chain) { gimple *src_stmt = gimple_range_ssa_p (op) ? SSA_NAME_DEF_STMT (op) : NULL; - basic_block bb = gimple_bb (stmt); - if (!op_in_chain || (src_stmt != NULL && bb != gimple_bb (src_stmt))) + if (!op_in_chain || (src_stmt != NULL + && gimple_bb (stmt) != gimple_bb (src_stmt))) { // If op is not in the def chain, or defined in this block, // use its known value on entry to the block. - expr_range_in_bb (range.true_range, name, gimple_bb (stmt)); + expr_range_at_stmt (range.true_range, name, stmt); range.false_range = range.true_range; return; } @@ -861,9 +920,9 @@ gori_compute::compute_logical_operands_in_chain (tf_range &range, // Calculate ranges for true and false on both sides, since the false // path is not always a simple inversion of the true side. if (!compute_operand_range (range.true_range, src_stmt, m_bool_one, name)) - expr_range_in_bb (range.true_range, name, bb); + expr_range_at_stmt (range.true_range, name, stmt); if (!compute_operand_range (range.false_range, src_stmt, m_bool_zero, name)) - expr_range_in_bb (range.false_range, name, bb); + expr_range_at_stmt (range.false_range, name, stmt); } // Given a logical STMT, calculate true and false for each potential @@ -881,10 +940,8 @@ gori_compute::compute_logical_operands (irange &r, gimple *stmt, tree op2 = gimple_range_operand2 (stmt); gcc_checking_assert (op1 != name && op2 != name); - bool op1_in_chain = (gimple_range_ssa_p (op1) - && m_gori_map->in_chain_p (name, op1)); - bool op2_in_chain = (gimple_range_ssa_p (op2) - && m_gori_map->in_chain_p (name, op2)); + bool op1_in_chain = (gimple_range_ssa_p (op1) && in_chain_p (name, op1)); + bool op2_in_chain = (gimple_range_ssa_p (op2) && in_chain_p (name, op2)); // If neither operand is derived, then this stmt tells us nothing. if (!op1_in_chain && !op2_in_chain) @@ -911,12 +968,12 @@ gori_compute::compute_operand1_range (irange &r, gimple *stmt, tree op1 = gimple_range_operand1 (stmt); tree op2 = gimple_range_operand2 (stmt); - expr_range_in_bb (op1_range, op1, gimple_bb (stmt)); + expr_range_at_stmt (op1_range, op1, stmt); // Now calcuated the operand and put that result in r. if (op2) { - expr_range_in_bb (op2_range, op2, gimple_bb (stmt)); + expr_range_at_stmt (op2_range, op2, stmt); if (!gimple_range_calc_op1 (r, stmt, lhs, op2_range)) return false; } @@ -958,8 +1015,8 @@ gori_compute::compute_operand2_range (irange &r, gimple *stmt, tree op1 = gimple_range_operand1 (stmt); tree op2 = gimple_range_operand2 (stmt); - expr_range_in_bb (op1_range, op1, gimple_bb (stmt)); - expr_range_in_bb (op2_range, op2, gimple_bb (stmt)); + expr_range_at_stmt (op1_range, op1, stmt); + expr_range_at_stmt (op2_range, op2, stmt); // Intersect with range for op2 based on lhs and op1. if (!gimple_range_calc_op2 (r, stmt, lhs, op1_range)) @@ -1014,18 +1071,9 @@ gori_compute::has_edge_range_p (tree name, edge e) { // If no edge is specified, check if NAME is an export on any edge. if (!e) - return m_gori_map->is_export_p (name); - - return (m_gori_map->is_export_p (name, e->src) - || m_gori_map->def_chain_in_export_p (name, e->src)); -} + return is_export_p (name); -// Clear the m_maybe_variant bit so ranges will not be tracked for NAME. - -void -gori_compute::set_range_invariant (tree name) -{ - m_gori_map->set_range_invariant (name); + return is_export_p (name, e->src); } // Dump what is known to GORI computes to listing file F. @@ -1033,7 +1081,7 @@ gori_compute::set_range_invariant (tree name) void gori_compute::dump (FILE *f) { - m_gori_map->dump (f); + gori_map::dump (f); } // Calculate a range on edge E and return it in R. Try to evaluate a @@ -1052,7 +1100,7 @@ gori_compute::outgoing_edge_range_p (irange &r, edge e, tree name) return false; // If NAME can be calculated on the edge, use that. - if (m_gori_map->is_export_p (name, e->src)) + if (is_export_p (name, e->src)) { if (compute_operand_range (r, stmt, lhs, name)) { @@ -1070,312 +1118,45 @@ gori_compute::outgoing_edge_range_p (irange &r, edge e, tree name) return false; } -// -------------------------------------------------------------------------- -// Cache for SSAs that appear on the RHS of a boolean assignment. -// -// Boolean assignments of logical expressions (i.e. LHS = j_5 > 999) -// have SSA operands whose range depend on the LHS of the assigment. -// That is, the range of j_5 when LHS is true is different than when -// LHS is false. -// -// This class caches the TRUE/FALSE ranges of such SSAs to avoid -// recomputing. +// ------------------------------------------------------------------------ +// GORI iterator. Although we have bitmap iterators, don't expose that it +// is currently a bitmap. Use an export iterator to hide future changes. -class logical_stmt_cache -{ -public: - logical_stmt_cache (); - ~logical_stmt_cache (); - void set_range (tree lhs, tree name, const tf_range &); - bool get_range (tf_range &r, tree lhs, tree name) const; - bool cacheable_p (gimple *, const irange *lhs_range = NULL) const; - void dump (FILE *, gimple *stmt) const; - tree same_cached_name (tree lhs1, tree lh2) const; -private: - tree cached_name (tree lhs) const; - void slot_diagnostics (tree lhs, const tf_range &range) const; - struct cache_entry - { - cache_entry (tree name, const irange &t_range, const irange &f_range); - void dump (FILE *out) const; - tree name; - tf_range range; - }; - vec<cache_entry *> m_ssa_cache; -}; +// Construct a basic iterator over an export bitmap. -logical_stmt_cache::cache_entry::cache_entry (tree name, - const irange &t_range, - const irange &f_range) - : name (name), range (t_range, f_range) +gori_export_iterator::gori_export_iterator (bitmap b) { + bm = b; + if (b) + bmp_iter_set_init (&bi, b, 1, &y); } -logical_stmt_cache::logical_stmt_cache () -{ - m_ssa_cache.create (num_ssa_names + num_ssa_names / 10); - m_ssa_cache.safe_grow_cleared (num_ssa_names); -} - -logical_stmt_cache::~logical_stmt_cache () -{ - for (unsigned i = 0; i < m_ssa_cache.length (); ++i) - if (m_ssa_cache[i]) - delete m_ssa_cache[i]; - m_ssa_cache.release (); -} - -// Dump cache_entry to OUT. - -void -logical_stmt_cache::cache_entry::dump (FILE *out) const -{ - fprintf (out, "name="); - print_generic_expr (out, name, TDF_SLIM); - fprintf (out, " "); - range.true_range.dump (out); - fprintf (out, ", "); - range.false_range.dump (out); - fprintf (out, "\n"); -} -// Update range for cache entry of NAME as it appears in the defining -// statement of LHS. +// Move to the next export bitmap spot. void -logical_stmt_cache::set_range (tree lhs, tree name, const tf_range &range) +gori_export_iterator::next () { - unsigned version = SSA_NAME_VERSION (lhs); - if (version >= m_ssa_cache.length ()) - m_ssa_cache.safe_grow_cleared (num_ssa_names + num_ssa_names / 10); - - cache_entry *slot = m_ssa_cache[version]; - slot_diagnostics (lhs, range); - if (slot) - { - // The IL must have changed. Update the carried SSA name for - // consistency. Testcase is libgomp.fortran/doacross1.f90. - if (slot->name != name) - slot->name = name; - return; - } - m_ssa_cache[version] - = new cache_entry (name, range.true_range, range.false_range); -} - -// If there is a cached entry of NAME, set it in R and return TRUE, -// otherwise return FALSE. LHS is the defining statement where NAME -// appeared. - -bool -logical_stmt_cache::get_range (tf_range &r, tree lhs, tree name) const -{ - gcc_checking_assert (cacheable_p (SSA_NAME_DEF_STMT (lhs))); - if (cached_name (lhs) == name) - { - unsigned version = SSA_NAME_VERSION (lhs); - if (m_ssa_cache[version]) - { - r = m_ssa_cache[version]->range; - return true; - } - } - return false; + bmp_iter_next (&bi, &y); } -// If the defining statement of LHS is in the cache, return the SSA -// operand being cached. That is, return SSA for LHS = SSA .RELOP. OP2. - -tree -logical_stmt_cache::cached_name (tree lhs) const -{ - unsigned version = SSA_NAME_VERSION (lhs); - - if (version >= m_ssa_cache.length ()) - return NULL; - - if (m_ssa_cache[version]) - return m_ssa_cache[version]->name; - return NULL; -} -// Return TRUE if the cached name for LHS1 is the same as the -// cached name for LHS2. +// Fetch the name of the next export in the export list. Return NULL if +// iteration is done. tree -logical_stmt_cache::same_cached_name (tree lhs1, tree lhs2) const -{ - tree name = cached_name (lhs1); - if (name && name == cached_name (lhs2)) - return name; - return NULL; -} - -// Return TRUE if STMT is a statement we are interested in caching. -// LHS_RANGE is any known range for the LHS of STMT. - -bool -logical_stmt_cache::cacheable_p (gimple *stmt, const irange *lhs_range) const -{ - if (gimple_code (stmt) == GIMPLE_ASSIGN - && types_compatible_p (TREE_TYPE (gimple_assign_lhs (stmt)), - boolean_type_node) - && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME) - { - switch (gimple_expr_code (stmt)) - { - case TRUTH_AND_EXPR: - case BIT_AND_EXPR: - case TRUTH_OR_EXPR: - case BIT_IOR_EXPR: - return !lhs_range || range_is_either_true_or_false (*lhs_range); - default: - return false; - } - } - return false; -} - -// Output debugging diagnostics for the cache entry for LHS. RANGE is -// the new range that is being cached. - -void -logical_stmt_cache::slot_diagnostics (tree lhs, const tf_range &range) const -{ - gimple *stmt = SSA_NAME_DEF_STMT (lhs); - unsigned version = SSA_NAME_VERSION (lhs); - cache_entry *slot = m_ssa_cache[version]; - - if (!slot) - { - if (DEBUG_RANGE_CACHE) - { - fprintf (dump_file ? dump_file : stderr, "registering range for: "); - dump (dump_file ? dump_file : stderr, stmt); - } - return; - } - if (DEBUG_RANGE_CACHE) - fprintf (dump_file ? dump_file : stderr, - "reusing range for SSA #%d\n", version); - if (CHECKING_P && (slot->range.true_range != range.true_range - || slot->range.false_range != range.false_range)) - { - fprintf (stderr, "FATAL: range altered for cached: "); - dump (stderr, stmt); - fprintf (stderr, "Attempt to change to:\n"); - fprintf (stderr, "TRUE="); - range.true_range.dump (stderr); - fprintf (stderr, ", FALSE="); - range.false_range.dump (stderr); - fprintf (stderr, "\n"); - gcc_unreachable (); - } -} - -// Dump the cache information for STMT. - -void -logical_stmt_cache::dump (FILE *out, gimple *stmt) const -{ - tree lhs = gimple_assign_lhs (stmt); - cache_entry *entry = m_ssa_cache[SSA_NAME_VERSION (lhs)]; - - print_gimple_stmt (out, stmt, 0, TDF_SLIM); - if (entry) - { - fprintf (out, "\tname = "); - print_generic_expr (out, entry->name); - fprintf (out, " lhs(%d)= ", SSA_NAME_VERSION (lhs)); - print_generic_expr (out, lhs); - fprintf (out, "\n\tTRUE="); - entry->range.true_range.dump (out); - fprintf (out, ", FALSE="); - entry->range.false_range.dump (out); - fprintf (out, "\n"); - } - else - fprintf (out, "[EMPTY]\n"); -} - -gori_compute_cache::gori_compute_cache () -{ - m_cache = new logical_stmt_cache; -} - -gori_compute_cache::~gori_compute_cache () -{ - delete m_cache; -} - -// Caching version of compute_operand_range. If NAME, as it appears -// in STMT, has already been cached return it from the cache, -// otherwise compute the operand range as normal and cache it. - -bool -gori_compute_cache::compute_operand_range (irange &r, gimple *stmt, - const irange &lhs_range, tree name) -{ - bool cacheable = m_cache->cacheable_p (stmt, &lhs_range); - if (cacheable) - { - tree lhs = gimple_assign_lhs (stmt); - tf_range range; - if (m_cache->get_range (range, lhs, name)) - { - if (lhs_range.zero_p ()) - r = range.false_range; - else - r = range.true_range; - return true; - } - } - if (super::compute_operand_range (r, stmt, lhs_range, name)) - { - if (cacheable) - cache_stmt (stmt); - return true; - } - return false; -} - -// Cache STMT if possible. - -void -gori_compute_cache::cache_stmt (gimple *stmt) +gori_export_iterator::get_name () { - gcc_checking_assert (m_cache->cacheable_p (stmt)); - enum tree_code code = gimple_expr_code (stmt); - tree lhs = gimple_assign_lhs (stmt); - tree op1 = gimple_range_operand1 (stmt); - tree op2 = gimple_range_operand2 (stmt); - int_range_max r_true_side, r_false_side; + if (!bm) + return NULL_TREE; - // LHS = s_5 && 999. - if (TREE_CODE (op2) == INTEGER_CST) - { - range_operator *handler = range_op_handler (code, TREE_TYPE (lhs)); - int_range_max op2_range; - expr_range_in_bb (op2_range, op2, gimple_bb (stmt)); - tree type = TREE_TYPE (op1); - handler->op1_range (r_true_side, type, m_bool_one, op2_range); - handler->op1_range (r_false_side, type, m_bool_zero, op2_range); - m_cache->set_range (lhs, op1, tf_range (r_true_side, r_false_side)); - } - // LHS = s_5 && b_8. - else if (tree cached_name = m_cache->same_cached_name (op1, op2)) + while (bmp_iter_set (&bi, &y)) { - tf_range op1_range, op2_range; - bool ok = m_cache->get_range (op1_range, op1, cached_name); - ok = ok && m_cache->get_range (op2_range, op2, cached_name); - ok = ok && logical_combine (r_true_side, code, m_bool_one, - op1_range, op2_range); - ok = ok && logical_combine (r_false_side, code, m_bool_zero, - op1_range, op2_range); - gcc_checking_assert (ok); - if (ok) - m_cache->set_range (lhs, cached_name, - tf_range (r_true_side, r_false_side)); + tree t = ssa_name (y); + if (t) + return t; + next (); } + return NULL_TREE; } diff --git a/gcc/gimple-range-gori.h b/gcc/gimple-range-gori.h index 7bb18a9..f41dee3 100644 --- a/gcc/gimple-range-gori.h +++ b/gcc/gimple-range-gori.h @@ -22,6 +22,90 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_GIMPLE_RANGE_GORI_H #define GCC_GIMPLE_RANGE_GORI_H +// RANGE_DEF_CHAIN is used to determine which SSA names in a block can +// have range information calculated for them, and what the +// dependencies on each other are. + +class range_def_chain +{ +public: + range_def_chain (); + ~range_def_chain (); + tree depend1 (tree name) const; + tree depend2 (tree name) const; + bool in_chain_p (tree name, tree def); + bool chain_import_p (tree name, tree import); + void register_dependency (tree name, tree ssa1, basic_block bb = NULL); + void dump (FILE *f, basic_block bb, const char *prefix = NULL); +protected: + bool has_def_chain (tree name); + bool def_chain_in_bitmap_p (tree name, bitmap b); + void add_def_chain_to_bitmap (bitmap b, tree name); + bitmap get_def_chain (tree name); + bitmap get_imports (tree name); + bitmap_obstack m_bitmaps; +private: + struct rdc { + tree ssa1; // First direct dependency + tree ssa2; // Second direct dependency + bitmap bm; // All dependencies + bitmap m_import; + }; + vec<rdc> m_def_chain; // SSA_NAME : def chain components. + void set_import (struct rdc &data, tree imp, bitmap b); + int m_logical_depth; +}; + +// Return the first direct dependency for NAME, if there is one. +// Direct dependencies are those which occur on the defintion statement. +// Only the first 2 such names are cached. + +inline tree +range_def_chain::depend1 (tree name) const +{ + unsigned v = SSA_NAME_VERSION (name); + if (v >= m_def_chain.length ()) + return NULL_TREE; + return m_def_chain[v].ssa1; +} + +// Return the second direct dependency for NAME, if there is one. + +inline tree +range_def_chain::depend2 (tree name) const +{ + unsigned v = SSA_NAME_VERSION (name); + if (v >= m_def_chain.length ()) + return NULL_TREE; + return m_def_chain[v].ssa2; +} + +// GORI_MAP is used to accumulate what SSA names in a block can +// generate range information, and provides tools for the block ranger +// to enable it to efficiently calculate these ranges. + +class gori_map : public range_def_chain +{ +public: + gori_map (); + ~gori_map (); + + bool is_export_p (tree name, basic_block bb = NULL); + bool is_import_p (tree name, basic_block bb); + bitmap exports (basic_block bb); + bitmap imports (basic_block bb); + void set_range_invariant (tree name); + + void dump (FILE *f); + void dump (FILE *f, basic_block bb, bool verbose = true); +private: + vec<bitmap> m_outgoing; // BB: Outgoing ranges calculatable on edges + vec<bitmap> m_incoming; // BB: Incoming ranges which can affect exports. + bitmap m_maybe_variant; // Names which might have outgoing ranges. + void maybe_add_gori (tree name, basic_block bb); + void calculate_gori (basic_block bb); +}; + // This class is used to determine which SSA_NAMES can have ranges // calculated for them on outgoing edges from basic blocks. This represents @@ -65,21 +149,19 @@ along with GCC; see the file COPYING3. If not see // // The remaining routines are internal use only. -class gori_compute +class gori_compute : public gori_map { public: gori_compute (); - ~gori_compute (); bool outgoing_edge_range_p (irange &r, edge e, tree name); bool has_edge_range_p (tree name, edge e = NULL); - void set_range_invariant (tree name); void dump (FILE *f); protected: virtual void ssa_range_in_bb (irange &r, tree name, basic_block bb); - virtual bool compute_operand_range (irange &r, gimple *stmt, - const irange &lhs, tree name); + bool compute_operand_range (irange &r, gimple *stmt, + const irange &lhs, tree name); - void expr_range_in_bb (irange &r, tree expr, basic_block bb); + void expr_range_at_stmt (irange &r, tree expr, gimple *s); bool compute_logical_operands (irange &r, gimple *stmt, const irange &lhs, tree name); @@ -107,36 +189,32 @@ private: bool compute_operand1_and_operand2_range (irange &r, gimple *stmt, const irange &lhs, tree name); - class gori_map *m_gori_map; gimple_outgoing_range outgoing; // Edge values for COND_EXPR & SWITCH_EXPR. }; -// This class adds a cache to gori_computes for logical expressions. -// bool result = x && y -// requires calcuation of both X and Y for both true and false results. -// There are 4 combinations [0,0][0,0] [0,0][1,1] [1,1][0,0] and [1,1][1,1]. -// Note that each pair of possible results for X and Y are used twice, and -// the calcuation of those results are the same each time. -// -// The cache simply checks if a stmt is cachable, and if so, saves both the -// true and false results for the next time the query is made. -// -// This is used to speed up long chains of logical operations which -// quickly become exponential. +// For each name that is an import into BB's exports.. +#define FOR_EACH_GORI_IMPORT_NAME(gori, bb, name) \ + for (gori_export_iterator iter ((gori).imports ((bb))); \ + ((name) = iter.get_name ()); \ + iter.next ()) -class gori_compute_cache : public gori_compute -{ +// For each name possibly exported from block BB. +#define FOR_EACH_GORI_EXPORT_NAME(gori, bb, name) \ + for (gori_export_iterator iter ((gori).exports ((bb))); \ + ((name) = iter.get_name ()); \ + iter.next ()) + +// Used to assist with iterating over the GORI export list in various ways +class gori_export_iterator { public: - gori_compute_cache (); - ~gori_compute_cache (); + gori_export_iterator (bitmap b); + void next (); + tree get_name (); protected: - virtual bool compute_operand_range (irange &r, gimple *stmt, - const irange &lhs, tree name); -private: - void cache_stmt (gimple *); - typedef gori_compute super; - class logical_stmt_cache *m_cache; + bitmap bm; + bitmap_iterator bi; + unsigned y; }; #endif // GCC_GIMPLE_RANGE_GORI_H diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc index 06e9804..e2d24d6 100644 --- a/gcc/gimple-range.cc +++ b/gcc/gimple-range.cc @@ -435,17 +435,17 @@ fold_using_range::range_of_range_op (irange &r, gimple *s, fur_source &src) // Fold range, and register any dependency if available. int_range<2> r2 (type); handler->fold_range (r, type, range1, r2); - if (lhs && src.m_cache) - src.m_cache->register_dependency (lhs, op1); + if (lhs && src.m_gori) + src.m_gori->register_dependency (lhs, op1); } else if (src.get_operand (range2, op2)) { // Fold range, and register any dependency if available. handler->fold_range (r, type, range1, range2); - if (lhs && src.m_cache) + if (lhs && src.m_gori) { - src.m_cache->register_dependency (lhs, op1); - src.m_cache->register_dependency (lhs, op2); + src.m_gori->register_dependency (lhs, op1); + src.m_gori->register_dependency (lhs, op2); } } else @@ -485,8 +485,8 @@ fold_using_range::range_of_address (irange &r, gimple *stmt, fur_source &src) { tree ssa = TREE_OPERAND (base, 0); tree lhs = gimple_get_lhs (stmt); - if (src.m_cache && lhs && gimple_range_ssa_p (ssa)) - src.m_cache->register_dependency (lhs, ssa); + if (src.m_gori && lhs && gimple_range_ssa_p (ssa)) + src.m_gori->register_dependency (lhs, ssa); gcc_checking_assert (irange::supports_type_p (TREE_TYPE (ssa))); src.get_operand (r, ssa); range_cast (r, TREE_TYPE (gimple_assign_rhs1 (stmt))); @@ -563,8 +563,8 @@ fold_using_range::range_of_phi (irange &r, gphi *phi, fur_source &src) edge e = gimple_phi_arg_edge (phi, x); // Register potential dependencies for stale value tracking. - if (src.m_cache && gimple_range_ssa_p (arg)) - src.m_cache->register_dependency (phi_def, arg); + if (src.m_gori && gimple_range_ssa_p (arg)) + src.m_gori->register_dependency (phi_def, arg); // Get the range of the argument on its edge. fur_source e_src (src.m_query, e); @@ -976,23 +976,16 @@ gimple_ranger::range_of_expr (irange &r, tree expr, gimple *stmt) // If name is defined in this block, try to get an range from S. if (def_stmt && gimple_bb (def_stmt) == bb) - range_of_stmt (r, def_stmt, expr); + { + range_of_stmt (r, def_stmt, expr); + if (!cfun->can_throw_non_call_exceptions && r.varying_p () && + m_cache.m_non_null.non_null_deref_p (expr, bb)) + r = range_nonzero (TREE_TYPE (expr)); + } else // Otherwise OP comes from outside this block, use range on entry. range_on_entry (r, bb, expr); - // No range yet, see if there is a dereference in the block. - // We don't care if it's between the def and a use within a block - // because the entire block must be executed anyway. - // FIXME:?? For non-call exceptions we could have a statement throw - // which causes an early block exit. - // in which case we may need to walk from S back to the def/top of block - // to make sure the deref happens between S and there before claiming - // there is a deref. Punt for now. - if (!cfun->can_throw_non_call_exceptions && r.varying_p () && - m_cache.m_non_null.non_null_deref_p (expr, bb)) - r = range_nonzero (TREE_TYPE (expr)); - return true; } @@ -1010,6 +1003,10 @@ gimple_ranger::range_on_entry (irange &r, basic_block bb, tree name) // Now see if there is any on_entry value which may refine it. if (m_cache.block_range (entry_range, bb, name)) r.intersect (entry_range); + + if (!cfun->can_throw_non_call_exceptions && r.varying_p () && + m_cache.m_non_null.non_null_deref_p (name, bb)) + r = range_nonzero (TREE_TYPE (name)); } // Calculate the range for NAME at the end of block BB and return it in R. @@ -1032,13 +1029,7 @@ gimple_ranger::range_on_exit (irange &r, basic_block bb, tree name) if (s) range_of_expr (r, name, s); else - { - range_on_entry (r, bb, name); - // See if there was a deref in this block, if applicable - if (!cfun->can_throw_non_call_exceptions && r.varying_p () && - m_cache.m_non_null.non_null_deref_p (name, bb)) - r = range_nonzero (TREE_TYPE (name)); - } + range_on_entry (r, bb, name); gcc_checking_assert (r.undefined_p () || range_compatible_p (r.type (), TREE_TYPE (name))); } @@ -1166,80 +1157,86 @@ gimple_ranger::export_global_ranges () // Print the known table values to file F. void -gimple_ranger::dump (FILE *f) +gimple_ranger::dump_bb (FILE *f, basic_block bb) { - basic_block bb; - - FOR_EACH_BB_FN (bb, cfun) - { - unsigned x; - edge_iterator ei; - edge e; - int_range_max range; - fprintf (f, "\n=========== BB %d ============\n", bb->index); - m_cache.dump (f, bb); + unsigned x; + edge_iterator ei; + edge e; + int_range_max range; + fprintf (f, "\n=========== BB %d ============\n", bb->index); + m_cache.dump (f, bb); - dump_bb (f, bb, 4, TDF_NONE); + ::dump_bb (f, bb, 4, TDF_NONE); - // Now find any globals defined in this block. - for (x = 1; x < num_ssa_names; x++) + // Now find any globals defined in this block. + for (x = 1; x < num_ssa_names; x++) + { + tree name = ssa_name (x); + if (gimple_range_ssa_p (name) && SSA_NAME_DEF_STMT (name) && + gimple_bb (SSA_NAME_DEF_STMT (name)) == bb && + m_cache.get_global_range (range, name)) { - tree name = ssa_name (x); - if (gimple_range_ssa_p (name) && SSA_NAME_DEF_STMT (name) && - gimple_bb (SSA_NAME_DEF_STMT (name)) == bb && - m_cache.get_global_range (range, name)) + if (!range.varying_p ()) { - if (!range.varying_p ()) - { - print_generic_expr (f, name, TDF_SLIM); - fprintf (f, " : "); - range.dump (f); - fprintf (f, "\n"); - } - + print_generic_expr (f, name, TDF_SLIM); + fprintf (f, " : "); + range.dump (f); + fprintf (f, "\n"); } + } + } - // And now outgoing edges, if they define anything. - FOR_EACH_EDGE (e, ei, bb->succs) + // And now outgoing edges, if they define anything. + FOR_EACH_EDGE (e, ei, bb->succs) + { + for (x = 1; x < num_ssa_names; x++) { - for (x = 1; x < num_ssa_names; x++) + tree name = gimple_range_ssa_p (ssa_name (x)); + if (name && m_cache.outgoing_edge_range_p (range, e, name)) { - tree name = gimple_range_ssa_p (ssa_name (x)); - if (name && m_cache.outgoing_edge_range_p (range, e, name)) + gimple *s = SSA_NAME_DEF_STMT (name); + // Only print the range if this is the def block, or + // the on entry cache for either end of the edge is + // set. + if ((s && bb == gimple_bb (s)) || + m_cache.block_range (range, bb, name, false) || + m_cache.block_range (range, e->dest, name, false)) { - gimple *s = SSA_NAME_DEF_STMT (name); - // Only print the range if this is the def block, or - // the on entry cache for either end of the edge is - // set. - if ((s && bb == gimple_bb (s)) || - m_cache.block_range (range, bb, name, false) || - m_cache.block_range (range, e->dest, name, false)) + range_on_edge (range, e, name); + if (!range.varying_p ()) { - range_on_edge (range, e, name); - if (!range.varying_p ()) - { - fprintf (f, "%d->%d ", e->src->index, - e->dest->index); - char c = ' '; - if (e->flags & EDGE_TRUE_VALUE) - fprintf (f, " (T)%c", c); - else if (e->flags & EDGE_FALSE_VALUE) - fprintf (f, " (F)%c", c); - else - fprintf (f, " "); - print_generic_expr (f, name, TDF_SLIM); - fprintf(f, " : \t"); - range.dump(f); - fprintf (f, "\n"); - } + fprintf (f, "%d->%d ", e->src->index, + e->dest->index); + char c = ' '; + if (e->flags & EDGE_TRUE_VALUE) + fprintf (f, " (T)%c", c); + else if (e->flags & EDGE_FALSE_VALUE) + fprintf (f, " (F)%c", c); + else + fprintf (f, " "); + print_generic_expr (f, name, TDF_SLIM); + fprintf(f, " : \t"); + range.dump(f); + fprintf (f, "\n"); } } } } } +} + +// Print the known table values to file F. + +void +gimple_ranger::dump (FILE *f) +{ + basic_block bb; + + FOR_EACH_BB_FN (bb, cfun) + dump_bb (f, bb); - m_cache.dump (dump_file, (dump_flags & TDF_DETAILS) != 0); + m_cache.dump (f, false); } // If SCEV has any information about phi node NAME, return it as a range in R. diff --git a/gcc/gimple-range.h b/gcc/gimple-range.h index 5320506..707dcfe 100644 --- a/gcc/gimple-range.h +++ b/gcc/gimple-range.h @@ -66,6 +66,7 @@ public: virtual void range_on_exit (irange &r, basic_block bb, tree name); void export_global_ranges (); void dump (FILE *f); + void dump_bb (FILE *f, basic_block bb); protected: bool fold_range_internal (irange &r, gimple *s, tree name); ranger_cache m_cache; @@ -83,10 +84,10 @@ class fur_source public: inline fur_source (range_query *q, edge e); inline fur_source (range_query *q, gimple *s); - inline fur_source (range_query *q, class ranger_cache *g, edge e, gimple *s); + inline fur_source (range_query *q, gori_compute *g, edge e, gimple *s); bool get_operand (irange &r, tree expr); protected: - ranger_cache *m_cache; + gori_compute *m_gori; range_query *m_query; edge m_edge; gimple *m_stmt; @@ -123,7 +124,7 @@ inline fur_source::fur_source (range_query *q, edge e) { m_query = q; - m_cache = NULL; + m_gori = NULL; m_edge = e; m_stmt = NULL; } @@ -134,7 +135,7 @@ inline fur_source::fur_source (range_query *q, gimple *s) { m_query = q; - m_cache = NULL; + m_gori = NULL; m_edge = NULL; m_stmt = s; } @@ -143,10 +144,10 @@ fur_source::fur_source (range_query *q, gimple *s) // and can also set the dependency information as appropriate when invoked. inline -fur_source::fur_source (range_query *q, ranger_cache *g, edge e, gimple *s) +fur_source::fur_source (range_query *q, gori_compute *g, edge e, gimple *s) { m_query = q; - m_cache = g; + m_gori = g; m_edge = e; m_stmt = s; } diff --git a/gcc/gimplify.c b/gcc/gimplify.c index b62ea0e..ed825a9 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -1828,6 +1828,9 @@ gimplify_decl_expr (tree *stmt_p, gimple_seq *seq_p) init = build2 (INIT_EXPR, void_type_node, decl, init); gimplify_and_add (init, seq_p); ggc_free (init); + /* Clear TREE_READONLY if we really have an initialization. */ + if (!DECL_INITIAL (decl)) + TREE_READONLY (decl) = 0; } else /* We must still examine initializers for static variables diff --git a/gcc/match.pd b/gcc/match.pd index 1fc6b7b..dd73081 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -3711,6 +3711,47 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (if (integer_all_onesp (@1) && integer_zerop (@2)) @0)))) +/* A few simplifications of "a ? CST1 : CST2". */ +/* NOTE: Only do this on gimple as the if-chain-to-switch + optimization depends on the gimple to have if statements in it. */ +#if GIMPLE +(simplify + (cond @0 INTEGER_CST@1 INTEGER_CST@2) + (switch + (if (integer_zerop (@2)) + (switch + /* a ? 1 : 0 -> a if 0 and 1 are integral types. */ + (if (integer_onep (@1)) + (convert (convert:boolean_type_node @0))) + /* a ? -1 : 0 -> -a. */ + (if (integer_all_onesp (@1)) + (negate (convert (convert:boolean_type_node @0)))) + /* a ? powerof2cst : 0 -> a << (log2(powerof2cst)) */ + (if (!POINTER_TYPE_P (type) && integer_pow2p (@1)) + (with { + tree shift = build_int_cst (integer_type_node, tree_log2 (@1)); + } + (lshift (convert (convert:boolean_type_node @0)) { shift; }))))) + (if (integer_zerop (@1)) + (with { + tree booltrue = constant_boolean_node (true, boolean_type_node); + } + (switch + /* a ? 0 : 1 -> !a. */ + (if (integer_onep (@2)) + (convert (bit_xor (convert:boolean_type_node @0) { booltrue; } ))) + /* a ? -1 : 0 -> -(!a). */ + (if (integer_all_onesp (@2)) + (negate (convert (bit_xor (convert:boolean_type_node @0) { booltrue; } )))) + /* a ? powerof2cst : 0 -> (!a) << (log2(powerof2cst)) */ + (if (!POINTER_TYPE_P (type) && integer_pow2p (@2)) + (with { + tree shift = build_int_cst (integer_type_node, tree_log2 (@2)); + } + (lshift (convert (bit_xor (convert:boolean_type_node @0) { booltrue; } )) + { shift; })))))))) +#endif + /* Simplification moved from fold_cond_expr_with_comparison. It may also be extended. */ /* This pattern implements two kinds simplification: @@ -4834,6 +4875,38 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (cmp (bit_and@2 @0 integer_pow2p@1) @1) (icmp @2 { build_zero_cst (TREE_TYPE (@0)); }))) +(for cmp (ge lt) +/* x < 0 ? ~y : y into (x >> (prec-1)) ^ y. */ +/* x >= 0 ? ~y : y into ~((x >> (prec-1)) ^ y). */ + (simplify + (cond (cmp @0 integer_zerop) (bit_not @1) @1) + (if (INTEGRAL_TYPE_P (type) + && INTEGRAL_TYPE_P (TREE_TYPE (@0)) + && !TYPE_UNSIGNED (TREE_TYPE (@0)) + && TYPE_PRECISION (TREE_TYPE (@0)) == TYPE_PRECISION (type)) + (with + { + tree shifter = build_int_cst (integer_type_node, TYPE_PRECISION (type) - 1); + } + (if (cmp == LT_EXPR) + (bit_xor (convert (rshift @0 {shifter;})) @1) + (bit_not (bit_xor (convert (rshift @0 {shifter;})) @1)))))) +/* x < 0 ? y : ~y into ~((x >> (prec-1)) ^ y). */ +/* x >= 0 ? y : ~y into (x >> (prec-1)) ^ y. */ + (simplify + (cond (cmp @0 integer_zerop) @1 (bit_not @1)) + (if (INTEGRAL_TYPE_P (type) + && INTEGRAL_TYPE_P (TREE_TYPE (@0)) + && !TYPE_UNSIGNED (TREE_TYPE (@0)) + && TYPE_PRECISION (TREE_TYPE (@0)) == TYPE_PRECISION (type)) + (with + { + tree shifter = build_int_cst (integer_type_node, TYPE_PRECISION (type) - 1); + } + (if (cmp == GE_EXPR) + (bit_xor (convert (rshift @0 {shifter;})) @1) + (bit_not (bit_xor (convert (rshift @0 {shifter;})) @1))))))) + /* If we have (A & C) != 0 ? D : 0 where C and D are powers of 2, convert this into a shift followed by ANDing with D. */ (simplify diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 00550f6..72d4f58 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,65 @@ +2021-05-25 Jakub Jelinek <jakub@redhat.com> + + PR c++/100666 + * g++.dg/cpp1z/nodiscard8.C: New test. + * g++.dg/cpp1z/nodiscard9.C: New test. + +2021-05-25 Martin Liska <mliska@suse.cz> + + * gcc.dg/sancov/attribute.c: New test. + +2021-05-25 Cooper Qu <cooper.qu@linux.alibaba.com> + + * gcc.target/csky/fpuv3/fpuv3.exp : Amend copyright. + +2021-05-25 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/99928 + * c-c++-common/gomp/pr99928-8.c: Remove xfails from omp teams r21 and + r28 checks. + * c-c++-common/gomp/pr99928-9.c: Likewise. + * c-c++-common/gomp/pr99928-10.c: Likewise. + +2021-05-25 Geng Qi <gengqi@linux.alibaba.com> + + * gcc.target/csky/fpuv3/fpuv3.exp: New. + * gcc.target/csky/fpuv3/fpv3_div.c: New. + * gcc.target/csky/fpuv3/fpv3_fadd.c: New. + * gcc.target/csky/fpuv3/fpv3_fdtos.c: New. + * gcc.target/csky/fpuv3/fpv3_fftoi_rm.c: New. + * gcc.target/csky/fpuv3/fpv3_fftoi_rz.c: New. + * gcc.target/csky/fpuv3/fpv3_fhtos.c: New. + * gcc.target/csky/fpuv3/fpv3_fitof.c: New. + * gcc.target/csky/fpuv3/fpv3_fmov.c: New. + * gcc.target/csky/fpuv3/fpv3_fmovi.c: New. + * gcc.target/csky/fpuv3/fpv3_fmula.c: New. + * gcc.target/csky/fpuv3/fpv3_fmuls.c: New. + * gcc.target/csky/fpuv3/fpv3_fneg.c: New. + * gcc.target/csky/fpuv3/fpv3_fnmula.c: New. + * gcc.target/csky/fpuv3/fpv3_fnmuls.c: New. + * gcc.target/csky/fpuv3/fpv3_fstod.c: New. + * gcc.target/csky/fpuv3/fpv3_fstoh.c: New. + * gcc.target/csky/fpuv3/fpv3_fsub.c: New. + * gcc.target/csky/fpuv3/fpv3_fxtof.c: New. + * gcc.target/csky/fpuv3/fpv3_h.c: New. + * gcc.target/csky/fpuv3/fpv3_hs.c: New. + * gcc.target/csky/fpuv3/fpv3_hsz.c: New. + * gcc.target/csky/fpuv3/fpv3_hz.c: New. + * gcc.target/csky/fpuv3/fpv3_ls.c: New. + * gcc.target/csky/fpuv3/fpv3_lsz.c: New. + * gcc.target/csky/fpuv3/fpv3_lt.c: New. + * gcc.target/csky/fpuv3/fpv3_ltz.c: New. + * gcc.target/csky/fpuv3/fpv3_max.c: New. + * gcc.target/csky/fpuv3/fpv3_min.c: New. + * gcc.target/csky/fpuv3/fpv3_mul.c: New. + * gcc.target/csky/fpuv3/fpv3_mula.c: New. + * gcc.target/csky/fpuv3/fpv3_muls.c: New. + * gcc.target/csky/fpuv3/fpv3_ne.c: New. + * gcc.target/csky/fpuv3/fpv3_nez.c: New. + * gcc.target/csky/fpuv3/fpv3_recip.c: New. + * gcc.target/csky/fpuv3/fpv3_sqrt.c: New. + * gcc.target/csky/fpuv3/fpv3_unordered.c: New. + 2021-05-24 Aaron Sawdey <acsawdey@linux.ibm.com> * gcc.target/powerpc/fusion-p10-logadd.c: New file. diff --git a/gcc/testsuite/g++.dg/cpp1z/nodiscard8.C b/gcc/testsuite/g++.dg/cpp1z/nodiscard8.C new file mode 100644 index 0000000..b5096ac --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/nodiscard8.C @@ -0,0 +1,15 @@ +// PR c++/100666 +// { dg-do compile { target c++11 } } + +[[nodiscard]] decltype(nullptr) bar (); +extern void foo (...); +template <typename T> void qux (T); + +void +baz () +{ + foo (bar ()); // { dg-bogus "ignoring return value of '\[^\n\r]*', declared with attribute 'nodiscard'" } + bar (); // { dg-warning "ignoring return value of '\[^\n\r]*', declared with attribute 'nodiscard'" } + auto x = bar (); // { dg-bogus "ignoring return value of '\[^\n\r]*', declared with attribute 'nodiscard'" } + qux (bar ()); // { dg-bogus "ignoring return value of '\[^\n\r]*', declared with attribute 'nodiscard'" } +} diff --git a/gcc/testsuite/g++.dg/cpp1z/nodiscard9.C b/gcc/testsuite/g++.dg/cpp1z/nodiscard9.C new file mode 100644 index 0000000..1315ccd --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/nodiscard9.C @@ -0,0 +1,22 @@ +// PR c++/100666 +// { dg-do compile { target c++11 } } + +struct S {}; +[[nodiscard]] S bar (); +struct U { S s; }; +[[nodiscard]] U corge (); +extern void foo (...); +template <typename T> void qux (T); + +void +baz () +{ + foo (bar ()); // { dg-bogus "ignoring return value of '\[^\n\r]*', declared with attribute 'nodiscard'" } + bar (); // { dg-warning "ignoring return value of '\[^\n\r]*', declared with attribute 'nodiscard'" } + auto x = bar (); // { dg-bogus "ignoring return value of '\[^\n\r]*', declared with attribute 'nodiscard'" } + qux (bar ()); // { dg-bogus "ignoring return value of '\[^\n\r]*', declared with attribute 'nodiscard'" } + foo (corge ()); // { dg-bogus "ignoring return value of '\[^\n\r]*', declared with attribute 'nodiscard'" } + corge (); // { dg-warning "ignoring return value of '\[^\n\r]*', declared with attribute 'nodiscard'" } + auto y = corge (); // { dg-bogus "ignoring return value of '\[^\n\r]*', declared with attribute 'nodiscard'" } + qux (corge ()); // { dg-bogus "ignoring return value of '\[^\n\r]*', declared with attribute 'nodiscard'" } +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr96928-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr96928-1.c new file mode 100644 index 0000000..a2770e5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr96928-1.c @@ -0,0 +1,48 @@ +/* PR tree-optimization/96928 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-phiopt2" } */ +/* { dg-final { scan-tree-dump-times " = a_\[0-9]*\\\(D\\\) >> " 5 "phiopt2" } } */ +/* { dg-final { scan-tree-dump-times " = ~c_\[0-9]*\\\(D\\\);" 1 "phiopt2" } } */ +/* { dg-final { scan-tree-dump-times " = ~" 1 "phiopt2" } } */ +/* { dg-final { scan-tree-dump-times " = \[abc_0-9\\\(\\\)D]* \\\^ " 5 "phiopt2" } } */ +/* { dg-final { scan-tree-dump-not "a < 0" "phiopt2" } } */ + +int +foo (int a) +{ + if (a < 0) + return ~a; + return a; +} + +int +bar (int a, int b) +{ + if (a < 0) + return ~b; + return b; +} + +unsigned +baz (int a, unsigned int b) +{ + if (a < 0) + return ~b; + return b; +} + +unsigned +qux (int a, unsigned int c) +{ + if (a >= 0) + return ~c; + return c; +} + +int +corge (int a, int b) +{ + if (a >= 0) + return b; + return ~b; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr96928.c b/gcc/testsuite/gcc.dg/tree-ssa/pr96928.c index 2091357..e8fd82f 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr96928.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr96928.c @@ -1,8 +1,11 @@ /* PR tree-optimization/96928 */ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-phiopt2" } */ +/* { dg-options "-O2 -fdump-tree-phiopt2 -fdump-tree-optimized" } */ /* { dg-final { scan-tree-dump-times " = a_\[0-9]*\\\(D\\\) >> " 5 "phiopt2" } } */ -/* { dg-final { scan-tree-dump-times " = ~c_\[0-9]*\\\(D\\\);" 1 "phiopt2" } } */ +/* The following check is done at optimized because a ^ (~b) is rewritten as ~(a^b) + and in the case of match.pd optimizing these ?:, the ~ is moved out already + by the time we get to phiopt2. */ +/* { dg-final { scan-tree-dump-times "\\\^ c_\[0-9]*\\\(D\\\);" 1 "optimized" } } */ /* { dg-final { scan-tree-dump-times " = ~" 1 "phiopt2" } } */ /* { dg-final { scan-tree-dump-times " = \[abc_0-9\\\(\\\)D]* \\\^ " 5 "phiopt2" } } */ /* { dg-final { scan-tree-dump-not "a < 0" "phiopt2" } } */ diff --git a/gcc/testsuite/gcc.target/csky/fldrd_fstrd.c b/gcc/testsuite/gcc.target/csky/fldrd_fstrd.c new file mode 100644 index 0000000..024de18 --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fldrd_fstrd.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-csky-options "-mcpu=ck810f -O1 -mhard-float" } */ + +double fldrd (double *pd, int index) +{ + return pd[index]; +} + +/* { dg-final { scan-assembler "fldrd" } } */ + +void fstrd (double *pd, int index, double d) +{ + pd[index] = d; +} + +/* { dg-final { scan-assembler "fstrd" } } */ + diff --git a/gcc/testsuite/gcc.target/csky/fpuv3/fldr64_fstr64.c b/gcc/testsuite/gcc.target/csky/fpuv3/fldr64_fstr64.c new file mode 100644 index 0000000..cd367e5 --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/fpuv3/fldr64_fstr64.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test is specific to ck860f" { csky-*-* } { "*" } { "-mcpu=ck860*f* -mfloat-abi=hard" "-mcpu=ck860*f* -mhard-float" } } */ +/* { dg-options "-O1 -mfpu=fpv3" } */ + +double fldr64 (double *pd, int index) +{ + return pd[index]; +} + +/* { dg-final { scan-assembler "fldr.64" } } */ + +void fstr64 (double *pd, int index, double d) +{ + pd[index] = d; +} + +/* { dg-final { scan-assembler "fstr.64" } } */ + diff --git a/gcc/testsuite/gcc.target/csky/ldbs.c b/gcc/testsuite/gcc.target/csky/ldbs.c new file mode 100644 index 0000000..27a0254 --- /dev/null +++ b/gcc/testsuite/gcc.target/csky/ldbs.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-mcpu=ck801" "-march=ck801" } { "*" } } */ +/* { dg-csky-options "-O1" } */ + +int foo (signed char *pb) +{ + return *pb; +} + +/* { dg-final { scan-assembler "ld.bs" } } */ + diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 8f945b8..1d13e7f 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -3446,7 +3446,7 @@ setup_one_parameter (copy_body_data *id, tree p, tree value, tree fn, sure that it cannot be modified from another path in the callee. */ if ((is_gimple_min_invariant (value) || (DECL_P (value) && TREE_READONLY (value)) - || (auto_var_in_fn_p (value, id->src_fn) + || (auto_var_in_fn_p (value, id->dst_fn) && !TREE_ADDRESSABLE (value))) && useless_type_conversion_p (TREE_TYPE (p), TREE_TYPE (value)) /* We have to be very careful about ADDR_EXPR. Make sure diff --git a/gcc/value-range.cc b/gcc/value-range.cc index 8d7b46c..f113fd7 100644 --- a/gcc/value-range.cc +++ b/gcc/value-range.cc @@ -2250,11 +2250,13 @@ range_tests_legacy () } // VARYING of different sizes should not be equal. - int_range_max r0 (integer_type_node); - int_range_max r1 (short_integer_type_node); + tree big_type = build_nonstandard_integer_type (32, 1); + tree small_type = build_nonstandard_integer_type (16, 1); + int_range_max r0 (big_type); + int_range_max r1 (small_type); ASSERT_TRUE (r0 != r1); - value_range vr0 (integer_type_node); - int_range_max vr1 (short_integer_type_node); + value_range vr0 (big_type); + int_range_max vr1 (small_type); ASSERT_TRUE (vr0 != vr1); } diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog index 8a5289a..accd3df 100644 --- a/libgomp/ChangeLog +++ b/libgomp/ChangeLog @@ -1,3 +1,8 @@ +2021-05-25 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/99928 + * testsuite/libgomp.c-c++-common/reduction-17.c: New test. + 2021-05-24 Tobias Burnus <tobias@codesourcery.com> PR fortran/86470 diff --git a/liboffloadmic/ChangeLog b/liboffloadmic/ChangeLog index c048f91..b027ed7 100644 --- a/liboffloadmic/ChangeLog +++ b/liboffloadmic/ChangeLog @@ -1,3 +1,9 @@ +2021-05-25 Richard Biener <rguenther@suse.de> + + PR libgomp/100747 + * configure: Make executable. + * plugin/configure: Likewise. + 2021-01-05 Samuel Thibault <samuel.thibault@ens-lyon.org> * configure: Re-generate. |