aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimple-range-fold.cc
AgeCommit message (Collapse)AuthorFilesLines
2024-02-21ipa: Convert lattices from pure array to vector (PR 113476)Martin Jambor1-0/+2
In PR 113476 we have discovered that ipcp_param_lattices is no longer a POD and should be destructed. In a follow-up discussion it transpired that their initialization done by memsetting their backing memory to zero is also invalid because now any write there before construction can be considered dead. Plus that having them in an array is a little bit old-school and does not get the extra checking offered by vector along with automatic construction and destruction when necessary. So this patch converts the array to a vector. That however means that ipcp_param_lattices cannot be just a forward declared type but must be known to all code that deals with ipa_node_params and thus to all code that includes ipa-prop.h. Therefore I have moved ipcp_param_lattices and the type it depends on to a new header ipa-cp.h which now ipa-prop.h depends on. Because we have the (IMHO not a very wise) rule that headers don't include what they need themselves, I had to add inclusions of ipa-cp.h and sreal.h (on which it depends) to very many files, which made the patch rather ugly. gcc/lto/ChangeLog: 2024-02-16 Martin Jambor <mjambor@suse.cz> PR ipa/113476 * lto-common.cc: Include sreal.h and ipa-cp.h. * lto-partition.cc: Include ipa-cp.h, move inclusion of sreal higher. * lto.cc: Include sreal.h and ipa-cp.h. gcc/ChangeLog: 2024-02-16 Martin Jambor <mjambor@suse.cz> PR ipa/113476 * ipa-prop.h (ipa_node_params): Convert lattices to a vector, adjust initializers in the contructor. (ipa_node_params::~ipa_node_params): Release lattices as a vector. * ipa-cp.h: New file. * ipa-cp.cc: Include sreal.h and ipa-cp.h. (ipcp_value_source): Move to ipa-cp.h. (ipcp_value_base): Likewise. (ipcp_value): Likewise. (ipcp_lattice): Likewise. (ipcp_agg_lattice): Likewise. (ipcp_bits_lattice): Likewise. (ipcp_vr_lattice): Likewise. (ipcp_param_lattices): Likewise. (ipa_get_parm_lattices): Remove assert latticess is non-NULL. (ipa_value_from_jfunc): Adjust a check for empty lattices. (ipa_context_from_jfunc): Likewise. (ipa_agg_value_from_jfunc): Likewise. (merge_agg_lats_step): Do not memset new aggregate lattices to zero. (ipcp_propagate_stage): Allocate lattices in a vector as opposed to just in contiguous memory. (ipcp_store_vr_results): Adjust a check for empty lattices. * auto-profile.cc: Include sreal.h and ipa-cp.h. * cgraph.cc: Likewise. * cgraphclones.cc: Likewise. * cgraphunit.cc: Likewise. * config/aarch64/aarch64.cc: Likewise. * config/i386/i386-builtins.cc: Likewise. * config/i386/i386-expand.cc: Likewise. * config/i386/i386-features.cc: Likewise. * config/i386/i386-options.cc: Likewise. * config/i386/i386.cc: Likewise. * config/rs6000/rs6000.cc: Likewise. * config/s390/s390.cc: Likewise. * gengtype.cc (open_base_files): Added sreal.h and ipa-cp.h to the files to be included in gtype-desc.cc. * gimple-range-fold.cc: Include sreal.h and ipa-cp.h. * ipa-devirt.cc: Likewise. * ipa-fnsummary.cc: Likewise. * ipa-icf.cc: Likewise. * ipa-inline-analysis.cc: Likewise. * ipa-inline-transform.cc: Likewise. * ipa-inline.cc: Include ipa-cp.h, move inclusion of sreal.h higher. * ipa-modref.cc: Include sreal.h and ipa-cp.h. * ipa-param-manipulation.cc: Likewise. * ipa-predicate.cc: Likewise. * ipa-profile.cc: Likewise. * ipa-prop.cc: Likewise. (ipa_node_params_t::duplicate): Assert new lattices remain empty instead of setting them to NULL. * ipa-pure-const.cc: Include sreal.h and ipa-cp.h. * ipa-split.cc: Likewise. * ipa-sra.cc: Likewise. * ipa-strub.cc: Likewise. * ipa-utils.cc: Likewise. * ipa.cc: Likewise. * toplev.cc: Likewise. * tree-ssa-ccp.cc: Likewise. * tree-ssa-sccvn.cc: Likewise. * tree-vrp.cc: Likewise.
2024-01-03Update copyright years.Jakub Jelinek1-1/+1
2023-11-20inter-procedural value range propagationJan Hubicka1-0/+24
implement very basic propapgation of return value ranges from VRP pass. This helps std::vector's push_back since we work out value range of allocated block. This propagates only within single translation unit. I hoped we will also do the propagation at WPA stage, but that needs more work on ipa-cp side. I also added code auto-detecting return_nonnull and corresponding -Wsuggest-attribute. gcc/ChangeLog: * cgraph.cc (add_detected_attribute_1): New function. (cgraph_node::add_detected_attribute): Likewise. * cgraph.h (cgraph_node::add_detected_attribute): Declare. * common.opt: Add -Wsuggest-attribute=returns_nonnull. * doc/invoke.texi: Document new flag. * gimple-range-fold.cc (fold_using_range::range_of_call): Use known reutrn value ranges. * ipa-prop.cc (struct ipa_return_value_summary): New type. (class ipa_return_value_sum_t): New type. (ipa_return_value_sum): New summary. (ipa_record_return_value_range): New function. (ipa_return_value_range): New function. * ipa-prop.h (ipa_return_value_range): Declare. (ipa_record_return_value_range): Declare. * ipa-pure-const.cc (warn_function_returns_nonnull): New funcion. * ipa-utils.h (warn_function_returns_nonnull): Declare. * symbol-summary.h: Fix comment. * tree-vrp.cc (execute_ranger_vrp): Record return values. gcc/testsuite/ChangeLog: * g++.dg/ipa/devirt-2.C: Add noipa attribute to prevent ipa-vrp. * g++.dg/ipa/devirt-7.C: Disable ipa-vrp. * g++.dg/ipa/ipa-icf-2.C: Disable ipa-vrp. * g++.dg/ipa/ipa-icf-3.C: Disable ipa-vrp. * g++.dg/ipa/ivinline-1.C: Disable ipa-vrp. * g++.dg/ipa/ivinline-3.C: Disable ipa-vrp. * g++.dg/ipa/ivinline-5.C: Disable ipa-vrp. * g++.dg/ipa/ivinline-8.C: Disable ipa-vrp. * g++.dg/ipa/nothrow-1.C: Disable ipa-vrp. * g++.dg/ipa/pure-const-1.C: Disable ipa-vrp. * g++.dg/ipa/pure-const-2.C: Disable ipa-vrp. * g++.dg/lto/inline-crossmodule-1_0.C: Disable ipa-vrp. * gcc.c-torture/compile/pr106433.c: Add noipa attribute to prevent ipa-vrp. * gcc.c-torture/execute/frame-address.c: Likewise. * gcc.dg/vla-1.c: Add noipa attribute to prevent ipa-vrp. * gcc.dg/ipa/fopt-info-inline-1.c: Disable ipa-vrp. * gcc.dg/ipa/ipa-icf-25.c: Disable ipa-vrp. * gcc.dg/ipa/ipa-icf-38.c: Disable ipa-vrp. * gcc.dg/ipa/pure-const-1.c: Disable ipa-vrp. * gcc.dg/ipa/remref-0.c: Add noipa attribute to prevent ipa-vrp. * gcc.dg/tree-prof/time-profiler-1.c: Disable ipa-vrp. * gcc.dg/tree-prof/time-profiler-2.c: Disable ipa-vrp. * gcc.dg/tree-ssa/pr110269.c: Disable ipa-vrp. * gcc.dg/tree-ssa/pr20701.c: Disable ipa-vrp. * gcc.dg/tree-ssa/vrp05.c: Disable ipa-vrp. * gcc.dg/tree-ssa/return-value-range-1.c: New test.
2023-10-16use more get_range_queryJiufu Guo1-3/+1
For "get_global_range_query" SSA_NAME_RANGE_INFO can be queried. For "get_range_query", it could get more context-aware range info. And look at the implementation of "get_range_query", it returns global range if no local fun info. So, if not quering for SSA_NAME and not chaning the IL, it would be ok to use get_range_query to replace get_global_range_query. gcc/ChangeLog: * fold-const.cc (expr_not_equal_to): Replace get_global_range_query by get_range_query. * gimple-fold.cc (size_must_be_zero_p): Likewise. * gimple-range-fold.cc (fur_source::fur_source): Likewise. * gimple-ssa-warn-access.cc (check_nul_terminated_array): Likewise. * tree-dfa.cc (get_ref_base_and_extent): Likewise.
2023-09-15Always do PHI analysis and before loop analysis.Andrew MacLeod1-27/+26
PHI analysis wasn't being done if loop analysis found a value. Always do the PHI analysis, and run it for an iniital value before invoking loop analysis. * gimple-range-fold.cc (fold_using_range::range_of_phi): Always run phi analysis, and do it before loop analysis.
2023-09-15Fix indentation.Andrew MacLeod1-40/+40
No functio0nal change, indentation was incorrect. * gimple-range-fold.cc (fold_using_range::range_of_phi): Fix indentation.
2023-08-23Phi analyzer - Initialize with range instead of a tree.Andrew MacLeod1-3/+3
Rangers PHI analyzer currently only allows a single initializer to a group. This patch changes that to use an inialization range, which is cumulative of all integer constants, plus a single symbolic value. There is no other change to group functionality. This patch also changes the way PHI groups are printed so they show up in the listing as they are encountered, rather than as a list at the end. It was more difficult to see what was going on previously. PR tree-optimization/110918 - Initialize with range instead of a tree. gcc/ * gimple-range-fold.cc (fold_using_range::range_of_phi): Tweak output. * gimple-range-phi.cc (phi_group::phi_group): Remove unused members. Initialize using a range instead of value and edge. (phi_group::calculate_using_modifier): Use initializer value and process for relations after trying for iteration convergence. (phi_group::refine_using_relation): Use initializer range. (phi_group::dump): Rework the dump output. (phi_analyzer::process_phi): Allow multiple constant initilizers. Dump groups immediately as created. (phi_analyzer::dump): Tweak output. * gimple-range-phi.h (phi_group::phi_group): Adjust prototype. (phi_group::initial_value): Delete. (phi_group::refine_using_relation): Adjust prototype. (phi_group::m_initial_value): Delete. (phi_group::m_initial_edge): Delete. (phi_group::m_vr): Use int_range_max. * tree-vrp.cc (execute_ranger_vrp): Don't dump phi groups. gcc/testsuite/ * gcc.dg/pr102983.c: Adjust output expectations. * gcc.dg/pr110918.c: New.
2023-08-03Add operand ranges to op1_op2_relation API.Andrew MacLeod1-10/+16
With additional floating point relations in the pipeline, we can no longer tell based on the LHS what the relation of X < Y is without knowing the type of X and Y. * gimple-range-fold.cc (fold_using_range::range_of_range_op): Add ranges to the call to relation_fold_and_or. (fold_using_range::relation_fold_and_or): Add op1 and op2 ranges. (fur_source::register_outgoing_edges): Add op1 and op2 ranges. * gimple-range-fold.h (relation_fold_and_or): Adjust params. * gimple-range-gori.cc (gori_compute::compute_operand_range): Add a varying op1 and op2 to call. * range-op-float.cc (range_operator::op1_op2_relation): New dafaults. (operator_equal::op1_op2_relation): New float version. (operator_not_equal::op1_op2_relation): Ditto. (operator_lt::op1_op2_relation): Ditto. (operator_le::op1_op2_relation): Ditto. (operator_gt::op1_op2_relation): Ditto. (operator_ge::op1_op2_relation) Ditto. * range-op-mixed.h (operator_equal::op1_op2_relation): New float prototype. (operator_not_equal::op1_op2_relation): Ditto. (operator_lt::op1_op2_relation): Ditto. (operator_le::op1_op2_relation): Ditto. (operator_gt::op1_op2_relation): Ditto. (operator_ge::op1_op2_relation): Ditto. * range-op.cc (range_op_handler::op1_op2_relation): Dispatch new variations. (range_operator::op1_op2_relation): Add extra params. (operator_equal::op1_op2_relation): Ditto. (operator_not_equal::op1_op2_relation): Ditto. (operator_lt::op1_op2_relation): Ditto. (operator_le::op1_op2_relation): Ditto. (operator_gt::op1_op2_relation): Ditto. (operator_ge::op1_op2_relation): Ditto. * range-op.h (range_operator): New prototypes. (range_op_handler): Ditto.
2023-07-31fur_list should not use the range vector for non-ssa operands.Andrew MacLeod1-1/+2
gcc/ PR tree-optimization/110582 * gimple-range-fold.cc (fur_list::get_operand): Do not use the range vector for non-ssa names. gcc/testsuite/ * gcc.dg/pr110582.c: New.
2023-06-15Check for integer only complex.Andrew MacLeod1-2/+4
With the expanded capabilities of range-op dispatch, floating point complex objects can appear when folding, whic they couldn't before. In the processig for extracting integers from complex ints, make sure it is an integer complex. PR tree-optimization/110266 gcc/ * gimple-range-fold.cc (adjust_imagpart_expr): Check for integer complex type. (adjust_realpart_expr): Ditto. gcc/testsuite/ * gcc.dg/pr110266.c: New.
2023-06-15middle-end, i386: Pattern recognize add/subtract with carry [PR79173]Jakub Jelinek1-0/+2
The following patch introduces {add,sub}c5_optab and pattern recognizes various forms of add with carry and subtract with carry/borrow, see pr79173-{1,2,3,4,5,6}.c tests on what is matched. Primarily forms with 2 __builtin_add_overflow or __builtin_sub_overflow calls per limb (with just one for the least significant one), for add with carry even when it is hand written in C (for subtraction reassoc seems to change it too much so that the pattern recognition doesn't work). __builtin_{add,sub}_overflow are standardized in C23 under ckd_{add,sub} names, so it isn't any longer a GNU only extension. Note, clang has for these (IMHO badly designed) __builtin_{add,sub}c{b,s,,l,ll} builtins which don't add/subtract just a single bit of carry, but basically add 3 unsigned values or subtract 2 unsigned values from one, and result in carry out of 0, 1, or 2 because of that. If we wanted to introduce those for clang compatibility, we could and lower them early to just two __builtin_{add,sub}_overflow calls and let the pattern matching in this patch recognize it later. I've added expanders for this on ix86 and in addition to that added various peephole2s (in preparation patches for this patch) to make sure we get nice (and small) code for the common cases. I think there are other PRs which request that e.g. for the _{addcarry,subborrow}_u{32,64} intrinsics, which the patch also improves. Would be nice if support for these optabs was added to many other targets, arm/aarch64 and powerpc* certainly have such instructions, I'd expect in fact that most targets do. The _BitInt support I'm working on will also need this to emit reasonable code. 2023-06-15 Jakub Jelinek <jakub@redhat.com> PR middle-end/79173 * internal-fn.def (UADDC, USUBC): New internal functions. * internal-fn.cc (expand_UADDC, expand_USUBC): New functions. (commutative_ternary_fn_p): Return true also for IFN_UADDC. * optabs.def (uaddc5_optab, usubc5_optab): New optabs. * tree-ssa-math-opts.cc (uaddc_cast, uaddc_ne0, uaddc_is_cplxpart, match_uaddc_usubc): New functions. (math_opts_dom_walker::after_dom_children): Call match_uaddc_usubc for PLUS_EXPR, MINUS_EXPR, BIT_IOR_EXPR and BIT_XOR_EXPR unless other optimizations have been successful for those. * gimple-fold.cc (gimple_fold_call): Handle IFN_UADDC and IFN_USUBC. * fold-const-call.cc (fold_const_call): Likewise. * gimple-range-fold.cc (adjust_imagpart_expr): Likewise. * tree-ssa-dce.cc (eliminate_unnecessary_stmts): Likewise. * doc/md.texi (uaddc<mode>5, usubc<mode>5): Document new named patterns. * config/i386/i386.md (uaddc<mode>5, usubc<mode>5): New define_expand patterns. (*setcc_qi_addqi3_cconly_overflow_1_<mode>, *setccc): Split into NOTE_INSN_DELETED note rather than nop instruction. (*setcc_qi_negqi_ccc_1_<mode>, *setcc_qi_negqi_ccc_2_<mode>): Likewise. * gcc.target/i386/pr79173-1.c: New test. * gcc.target/i386/pr79173-2.c: New test. * gcc.target/i386/pr79173-3.c: New test. * gcc.target/i386/pr79173-4.c: New test. * gcc.target/i386/pr79173-5.c: New test. * gcc.target/i386/pr79173-6.c: New test. * gcc.target/i386/pr79173-7.c: New test. * gcc.target/i386/pr79173-8.c: New test. * gcc.target/i386/pr79173-9.c: New test. * gcc.target/i386/pr79173-10.c: New test.
2023-05-24Gimple range PHI analyzer and testcasesAndrew MacLeod1-0/+27
Provide a PHI analyzer framework to provive better initial values for PHI nodes which formk groups with initial values and single statements which modify the PHI values in some predicatable way. PR tree-optimization/107822 PR tree-optimization/107986 gcc/ * Makefile.in (OBJS): Add gimple-range-phi.o. * gimple-range-cache.h (ranger_cache::m_estimate): New phi_analyzer pointer member. * gimple-range-fold.cc (fold_using_range::range_of_phi): Use phi_analyzer if no loop info is available. * gimple-range-phi.cc: New file. * gimple-range-phi.h: New file. * tree-vrp.cc (execute_ranger_vrp): Utililze a phi_analyzer. gcc/testsuite/ * gcc.dg/pr107822.c: New. * gcc.dg/pr107986-1.c: New.
2023-05-24Provide relation queries for a stmt.Andrew MacLeod1-12/+116
Allow fur_list and fold_stmt to be provided a range_query rather than always defaultsing to NULL (which becomes a global query). Also provide a fold_relations () routine which can provide a range_trio for an arbitrary statement using any range_query * gimple-range-fold.cc (fur_list::fur_list): Add range_query param to contructors. (fold_range): Add range_query parameter. (fur_relation::fur_relation): New. (fur_relation::trio): New. (fur_relation::register_relation): New. (fold_relations): New. * gimple-range-fold.h (fold_range): Adjust prototypes. (fold_relations): New.
2023-05-01Rewrite bounds_of_var_in_loop() to use ranges.Aldy Hernandez1-78/+2
Little by little, bounds_of_var_in_loop() has grown into an unmaintainable mess. This patch rewrites the code to use the relevant APIs as well as refactor it to make it more readable. gcc/ChangeLog: * gimple-range-fold.cc (tree_lower_bound): Delete. (tree_upper_bound): Delete. (vrp_val_max): Delete. (vrp_val_min): Delete. (fold_using_range::range_of_ssa_name_with_loop_info): Call range_of_var_in_loop. * vr-values.cc (valid_value_p): Delete. (fix_overflow): Delete. (get_scev_info): New. (bounds_of_var_in_loop): Refactor into... (induction_variable_may_overflow_p): ...this, (range_from_loop_direction): ...and this, (range_of_var_in_loop): ...and this. * vr-values.h (bounds_of_var_in_loop): Delete. (range_of_var_in_loop): New.
2023-05-01Replace vrp_val* with wide_ints.Aldy Hernandez1-4/+36
This patch removes all uses of vrp_val_{min,max} in favor for a irange_val_* which are wide_int based. This will leave only one use of vrp_val_* which returns trees in range_of_ssa_name_with_loop_info() because it needs to work with non-integers (floats, etc). In a follow-up patch, this function will also be cleaned up such that vrp_val_* can be deleted. The functions min_limit and max_limit in range-op.cc are now useless as they're basically irange_val*. I didn't rename them yet to avoid churn. I'll do it in a later patch. gcc/ChangeLog: * gimple-range-fold.cc (adjust_pointer_diff_expr): Rewrite with irange_val*. (vrp_val_max): New. (vrp_val_min): New. * gimple-range-op.cc (cfn_strlen::fold_range): Use irange_val_*. * range-op.cc (max_limit): Same. (min_limit): Same. (plus_minus_ranges): Same. (operator_rshift::op1_range): Same. (operator_cast::inside_domain_p): Same. * value-range.cc (vrp_val_is_max): Delete. (vrp_val_is_min): Delete. (range_tests_misc): Use irange_val_*. * value-range.h (vrp_val_is_min): Delete. (vrp_val_is_max): Delete. (vrp_val_max): Delete. (irange_val_min): New. (vrp_val_min): Delete. (irange_val_max): New. * vr-values.cc (check_for_binary_op_overflow): Use irange_val_*.
2023-05-01Conversion to irange wide_int API.Aldy Hernandez1-6/+8
This converts the irange API to use wide_ints exclusively, along with its users. This patch will slow down VRP, as there will be more useless wide_int to tree conversions. However, this slowdown is only temporary, as a follow-up patch will convert the internal representation of iranges to wide_ints for a net overall gain in performance. gcc/ChangeLog: * fold-const.cc (expr_not_equal_to): Convert to irange wide_int API. * gimple-fold.cc (size_must_be_zero_p): Same. * gimple-loop-versioning.cc (loop_versioning::prune_loop_conditions): Same. * gimple-range-edge.cc (gcond_edge_range): Same. (gimple_outgoing_range::calc_switch_ranges): Same. * gimple-range-fold.cc (adjust_imagpart_expr): Same. (adjust_realpart_expr): Same. (fold_using_range::range_of_address): Same. (fold_using_range::relation_fold_and_or): Same. * gimple-range-gori.cc (gori_compute::gori_compute): Same. (range_is_either_true_or_false): Same. * gimple-range-op.cc (cfn_toupper_tolower::get_letter_range): Same. (cfn_clz::fold_range): Same. (cfn_ctz::fold_range): Same. * gimple-range-tests.cc (class test_expr_eval): Same. * gimple-ssa-warn-alloca.cc (alloca_call_type): Same. * ipa-cp.cc (ipa_value_range_from_jfunc): Same. (propagate_vr_across_jump_function): Same. (decide_whether_version_node): Same. * ipa-prop.cc (ipa_get_value_range): Same. * ipa-prop.h (ipa_range_set_and_normalize): Same. * range-op.cc (get_shift_range): Same. (value_range_from_overflowed_bounds): Same. (value_range_with_overflow): Same. (create_possibly_reversed_range): Same. (equal_op1_op2_relation): Same. (not_equal_op1_op2_relation): Same. (lt_op1_op2_relation): Same. (le_op1_op2_relation): Same. (gt_op1_op2_relation): Same. (ge_op1_op2_relation): Same. (operator_mult::op1_range): Same. (operator_exact_divide::op1_range): Same. (operator_lshift::op1_range): Same. (operator_rshift::op1_range): Same. (operator_cast::op1_range): Same. (operator_logical_and::fold_range): Same. (set_nonzero_range_from_mask): Same. (operator_bitwise_or::op1_range): Same. (operator_bitwise_xor::op1_range): Same. (operator_addr_expr::fold_range): Same. (pointer_plus_operator::wi_fold): Same. (pointer_or_operator::op1_range): Same. (INT): Same. (UINT): Same. (INT16): Same. (UINT16): Same. (SCHAR): Same. (UCHAR): Same. (range_op_cast_tests): Same. (range_op_lshift_tests): Same. (range_op_rshift_tests): Same. (range_op_bitwise_and_tests): Same. (range_relational_tests): Same. * range.cc (range_zero): Same. (range_nonzero): Same. * range.h (range_true): Same. (range_false): Same. (range_true_and_false): Same. * tree-data-ref.cc (split_constant_offset_1): Same. * tree-ssa-loop-ch.cc (entry_loop_condition_is_static): Same. * tree-ssa-loop-unswitch.cc (struct unswitch_predicate): Same. (find_unswitching_predicates_for_bb): Same. * tree-ssa-phiopt.cc (value_replacement): Same. * tree-ssa-threadbackward.cc (back_threader::find_taken_edge_cond): Same. * tree-ssanames.cc (ssa_name_has_boolean_range): Same. * tree-vrp.cc (find_case_label_range): Same. * value-query.cc (range_query::get_tree_range): Same. * value-range.cc (irange::set_nonnegative): Same. (frange::contains_p): Same. (frange::singleton_p): Same. (frange::internal_singleton_p): Same. (irange::irange_set): Same. (irange::irange_set_1bit_anti_range): Same. (irange::irange_set_anti_range): Same. (irange::set): Same. (irange::operator==): Same. (irange::singleton_p): Same. (irange::contains_p): Same. (irange::set_range_from_nonzero_bits): Same. (DEFINE_INT_RANGE_INSTANCE): Same. (INT): Same. (UINT): Same. (SCHAR): Same. (UINT128): Same. (UCHAR): Same. (range): New. (tree_range): New. (range_int): New. (range_uint): New. (range_uint128): New. (range_uchar): New. (range_char): New. (build_range3): Convert to irange wide_int API. (range_tests_irange3): Same. (range_tests_int_range_max): Same. (range_tests_strict_enum): Same. (range_tests_misc): Same. (range_tests_nonzero_bits): Same. (range_tests_nan): Same. (range_tests_signed_zeros): Same. * value-range.h (Value_Range::Value_Range): Same. (irange::set): Same. (irange::nonzero_p): Same. (irange::contains_p): Same. (range_includes_zero_p): Same. (irange::set_nonzero): Same. (irange::set_zero): Same. (contains_zero_p): Same. (frange::contains_p): Same. * vr-values.cc (simplify_using_ranges::op_with_boolean_value_range_p): Same. (bounds_of_var_in_loop): Same. (simplify_using_ranges::legacy_fold_cond_overflow): Same.
2023-04-20Do not ignore UNDEFINED ranges when determining PHI equivalences.Andrew MacLeod1-8/+8
Do not ignore UNDEFINED name arguments when registering two-way equivalences from PHIs. PR tree-optimization/109564 gcc/ * gimple-range-fold.cc (fold_using_range::range_of_phi): Do no ignore UNDEFINED range names when deciding if all PHI arguments are the same, gcc/testsuite/ * gcc.dg/torture/pr109564-1.c: New testcase. * gcc.dg/torture/pr109564-2.c: Likewise. * gcc.dg/tree-ssa/evrp-ignore.c: XFAIL. * gcc.dg/tree-ssa/vrp06.c: Likewise.
2023-04-13Ensure PHI equivalencies do not dominate the argument edge.Andrew MacLeod1-2/+21
When we create an equivalency between a PHI definition and an argument, ensure the definition does not dominate the incoming argument edge. PR tree-optimization/108139 PR tree-optimization/109462 * gimple-range-cache.cc (ranger_cache::fill_block_cache): Remove equivalency check for PHI nodes. * gimple-range-fold.cc (fold_using_range::range_of_phi): Ensure def does not dominate single-arg equivalency edges.
2023-03-23ranger: Ranger meets aspellJakub Jelinek1-5/+5
I've noticed a comment typo in tree-vrp.cc and decided to quickly skim aspell -c on the ranger sources (with quick I on everything that looked ok or roughly ok). But not being a native English speaker, I could get stuff wrong. 2023-03-23 Jakub Jelinek <jakub@redhat.com> * value-range.cc (irange::irange_union, irange::intersect): Fix comment spelling bugs. * gimple-range-trace.cc (range_tracer::do_header): Likewise. * gimple-range-trace.h: Likewise. * gimple-range-edge.cc: Likewise. (gimple_outgoing_range_stmt_p, gimple_outgoing_range::switch_edge_range, gimple_outgoing_range::edge_range_p): Likewise. * gimple-range.cc (gimple_ranger::prefill_stmt_dependencies, gimple_ranger::fold_stmt, gimple_ranger::register_transitive_infer, assume_query::assume_query, assume_query::calculate_phi): Likewise. * gimple-range-edge.h: Likewise. * value-range.h (Value_Range::set, Value_Range::lower_bound, Value_Range::upper_bound, frange::set_undefined): Likewise. * gimple-range-gori.h (range_def_chain::depend, gori_map::m_outgoing, gori_compute): Likewise. * gimple-range-fold.h (fold_using_range): Likewise. * gimple-range-path.cc (path_range_query::compute_ranges_in_phis): Likewise. * gimple-range-gori.cc (range_def_chain::in_chain_p, range_def_chain::dump, gori_map::calculate_gori, gori_compute::compute_operand_range_switch, gori_compute::logical_combine, gori_compute::refine_using_relation, gori_compute::compute_operand1_range, gori_compute::may_recompute_p): Likewise. * gimple-range.h: Likewise. (enable_ranger): Likewise. * range-op.h (empty_range_varying): Likewise. * value-query.h (value_query): Likewise. * gimple-range-cache.cc (block_range_cache::set_bb_range, block_range_cache::dump, ssa_global_cache::clear_global_range, temporal_cache::temporal_value, temporal_cache::current_p, ranger_cache::range_of_def, ranger_cache::propagate_updated_value, ranger_cache::range_from_dom, ranger_cache::register_inferred_value): Likewise. * gimple-range-fold.cc (fur_edge::get_phi_operand, fur_stmt::get_operand, gimple_range_adjustment, fold_using_range::range_of_phi, fold_using_range::relation_fold_and_or): Likewise. * value-range-storage.h (irange_storage_slot::MAX_INTS): Likewise. * value-query.cc (range_query::value_of_expr, range_query::value_on_edge, range_query::query_relation): Likewise. * tree-vrp.cc (remove_unreachable::remove_and_update_globals, intersect_range_with_nonzero_bits): Likewise. * gimple-range-infer.cc (gimple_infer_range::check_assume_func, exit_range): Likewise. * value-relation.h: Likewise. (equiv_oracle, relation_trio::relation_trio, value_relation, value_relation::value_relation, pe_min): Likewise. * range-op-float.cc (range_operator_float::rv_fold, frange_arithmetic, foperator_unordered_equal::op1_range, foperator_div::rv_fold): Likewise. * gimple-range-op.cc (cfn_clz::fold_range): Likewise. * value-relation.cc (equiv_oracle::query_relation, equiv_oracle::register_equiv, equiv_oracle::add_equiv_to_block, value_relation::apply_transitive, relation_chain_head::find_relation, dom_oracle::query_relation, dom_oracle::find_relation_block, dom_oracle::find_relation_dom, path_oracle::register_equiv): Likewise. * range-op.cc (range_operator::wi_fold_in_parts_equiv, create_possibly_reversed_range, adjust_op1_for_overflow, operator_mult::wi_fold, operator_exact_divide::op1_range, operator_cast::lhs_op1_relation, operator_cast::fold_pair, operator_cast::fold_range, operator_abs::wi_fold, range_op_cast_tests, range_op_lshift_tests): Likewise.
2023-01-27Do not try to logical fold floating point relations.Andrew MacLeod1-0/+3
relation_fold_and_or looks for relations among common operands feeding logical ands and ors. With no knowledge of NANs, it should not attempt to do this with floating point ssa names. PR tree-optimization/108447 gcc/ * gimple-range-fold.cc (old_using_range::relation_fold_and_or): Do not attempt to fold HONOR_NAN types. gcc/testsuite/ * gcc.dg/pr108447.c: New.
2023-01-02Update copyright years.Jakub Jelinek1-1/+1
2022-10-26Check if varying may also be non-negative.Andrew MacLeod1-0/+8
When using strict enums, we can sometimes turn varying into a better range. * gimple-range-fold.cc (fold_using_range::fold_stmt): Check if stmt is non-negative and adjust the range.
2022-10-17Add relation_trio class for range-ops.Andrew MacLeod1-2/+3
There are 3 possible relations range-ops might care about, but only the one most likely to be needed is supplied. This patch provides a new class relation_trio which allows 3 relations to be passed in a single word. fold_range (), op1_range (), and op2_range () are adjusted to take a relation_trio class instead of a relation_kind, then the routine can extract which relation it wants to work with. * gimple-range-fold.cc (fold_using_range::range_of_range_op): Provide relation_trio class. * gimple-range-gori.cc (gori_compute::refine_using_relation): Provide relation_trio class. (gori_compute::refine_using_relation): Ditto. (gori_compute::compute_operand1_range): Provide lhs_op2 and op1_op2 relations via relation_trio class. (gori_compute::compute_operand2_range): Ditto. * gimple-range-op.cc (gimple_range_op_handler::calc_op1): Use relation_trio instead of relation_kind. (gimple_range_op_handler::calc_op2): Ditto. (*::fold_range): Ditto. * gimple-range-op.h (gimple_range_op::calc_op1): Adjust prototypes. (gimple_range_op::calc_op2): Adjust prototypes. * range-op-float.cc (*::fold_range): Use relation_trio instead of relation_kind. (*::op1_range): Ditto. (*::op2_range): Ditto. * range-op.cc (*::fold_range): Use relation_trio instead of relation_kind. (*::op1_range): Ditto. (*::op2_range): Ditto. * range-op.h (class range_operator): Adjust prototypes. (class range_operator_float): Ditto. (class range_op_handler): Adjust prototypes. (relop_early_resolve): Pickup op1_op2 relation from relation_trio. * value-relation.cc (VREL_LAST): Adjust use to be one past the end of the enum. (relation_oracle::validate_relation): Use relation_trio in call to fold_range. * value-relation.h (enum relation_kind_t): Add VREL_LAST as final element. (class relation_trio): New. (TRIO_VARYING, TRIO_SHIFT, TRIO_MASK): New.
2022-09-22Convert CFN_BUILT_IN_PARITY to range-ops.Andrew MacLeod1-48/+12
Also, as the last builtin remaining, also remove the builtin infrastrucure routines from fold_using_range. * gimple-range-fold.cc (range_of_range_op): Handle no operands. (range_of_call): Do not check for builtins. (fold_using_range::range_of_builtin_call): Delete. (fold_using_range::range_of_builtin_int_call): Delete. * gimple-range-fold.h: Adjust prototypes. * gimple-range-op.cc (class cfn_parity): New. (gimple_range_op_handler::maybe_builtin_call): Set arguments.
2022-09-22Convert CFN_BUILT_IN_GOACC_DIM_* to range-ops.Andrew MacLeod1-19/+0
* gimple-range-fold.cc (range_of_builtin_int_call): Remove case for CFN_GOACC_DIM_*. * gimple-range-op.cc (class cfn_goacc_dim): New. (gimple_range_op_handler::maybe_builtin_call): Set arguments.
2022-09-22Convert CFN_BUILT_IN_STRLEN to range-ops.Andrew MacLeod1-21/+0
* gimple-range-fold.cc (range_of_builtin_int_call): Remove case for CFN_BUILT_IN_STRLEN. * gimple-range-op.cc (class cfn_strlen): New. (gimple_range_op_handler::maybe_builtin_call): Set arguments.
2022-09-22Convert CFN_BUILT_IN_UBSAN_CHECK_* to range-ops.Andrew MacLeod1-46/+1
* gimple-range-fold.cc (range_of_builtin_ubsan_call): Delete. (range_of_builtin_int_call): Remove cases for CFN_BUILT_IN_UBSAN_CHECK. * gimple-range-op.cc (class cfn_ubsan): New. (gimple_range_op_handler::maybe_builtin_call): Set arguments.
2022-09-22Convert CFN_BUILT_IN_CLRSB to range-ops.Andrew MacLeod1-7/+0
* gimple-range-fold.cc (range_of_builtin_int_call): Remove case for CFN_BUILT_IN_CLRSB. * gimple-range-op.cc (class cfn_clrsb): New. (gimple_range_op_handler::maybe_builtin_call): Set arguments.
2022-09-22Convert CFN_CTZ builtins to range-ops.Andrew MacLeod1-60/+1
* gimple-range-fold.cc (range_of_builtin_int_call): Remove case for CFN_CTZ. * gimple-range-op.cc (class cfn_ctz): New. (gimple_range_op_handler::maybe_builtin_call): Set arguments.
2022-09-22Convert CFN_CLZ builtins to range-ops.Andrew MacLeod1-61/+0
* gimple-range-fold.cc (range_of_builtin_int_call): Remove case for CFN_CLZ. * gimple-range-op.cc (class cfn_clz): New. (gimple_range_op_handler::maybe_builtin_call): Set arguments.
2022-09-22Convert CFN_BUILT_FFS and CFN_POPCOUNT to range-ops.Andrew MacLeod1-22/+0
* gimple-range-fold.cc (range_of_builtin_int_call): Remove case for CFN_FFS and CFN_POPCOUNT. * gimple-range-op.cc (class cfn_pocount): New. (gimple_range_op_handler::maybe_builtin_call): Set arguments.
2022-09-22Convert CFN_BUILT_IN_TOUPPER and TOLOWER to range-ops.Andrew MacLeod1-66/+0
* gimple-range-fold.cc (get_letter_range): Move to new class. (range_of_builtin_int_call): Remove case for CFN_BUILT_IN_TOUPPER and CFN_BUILT_IN_TOLOWER. * gimple-range-op.cc (class cfn_toupper_tolower): New. (gimple_range_op_handler::maybe_builtin_call): Set arguments.
2022-09-22Convert CFN_BUILT_IN_SIGNBIT to range-ops.Andrew MacLeod1-20/+0
* gimple-range-fold.cc (range_of_builtin_int_call): Remove case for CFN_BUILT_IN_SIGNBIT. * gimple-range-op.cc (class cfn_signbit): New. (gimple_range_op_handler::maybe_builtin_call): Set arguments.
2022-09-22Add range-ops support for builtin functions.Andrew MacLeod1-17/+0
Convert CFN_BUILT_IN_CONSTANT_P as first POC. * gimple-range-fold.cc (fold_using_range::range_of_builtin_int_call): Remove case for CFN_BUILT_IN_CONSTANT_P. * gimple-range-op.cc (gimple_range_op_handler::supported_p): Check if a call also creates a range-op object. (gimple_range_op_handler): Also check builtin calls. (class cfn_constant_float_p): New. Float CFN_BUILT_IN_CONSTANT_P. (class cfn_constant_p): New. Integral CFN_BUILT_IN_CONSTANT_P. (gimple_range_op_handler::maybe_builtin_call): Set arguments and handler for supported built-in calls. * gimple-range-op.h (maybe_builtin_call): New prototype.
2022-09-22Always check the return value of fold_range.Andrew MacLeod1-2/+4
The fold_range routine in range-ops returns FALSE if the operation fails. There are a few places which assume the operation was successful. Fix those. * gimple-range-fold.cc (range_of_range_op): Set result to VARYING if the call to fold_range fails. * tree-data-ref.cc (compute_distributive_range): Ditto. * tree-vrp.cc (range_fold_binary_expr): Ditto. (range_fold_unary_expr): Ditto. * value-query.cc (range_query::get_tree_range): Ditto.
2022-09-22Create gimple_range_op_handler in a new source file.Andrew MacLeod1-125/+28
Range-ops is meant to be IL independent. Some gimple processing has be placed in range-ops, and some is located in gori. Split it all into a file and isolate it in a new class gimple_range_op_handler. * Makefile.in (OBJS): Add gimple-range-op.o. * gimple-range-edge.cc (gimple_outgoing_range_stmt_p): Use gimple_range_op_handler. * gimple-range-fold.cc (gimple_range_base_of_assignment): Move to a method in gimple_range_op_handler. (gimple_range_operand1): Ditto. (gimple_range_operand2): Ditto. (fold_using_range::fold_stmt): Use gimple_range_op_handler. (fold_using_range::range_of_range_op): Ditto. (fold_using_range::relation_fold_and_or): Ditto. (fur_source::register_outgoing_edges): Ditto. (gimple_range_ssa_names): Relocate to gimple-range-op.cc. * gimple-range-fold.h: Adjust prototypes. * gimple-range-gori.cc (gimple_range_calc_op1): Move to a method in gimple_range_op_handler. (gimple_range_calc_op2): Ditto. (gori_compute::compute_operand_range): Use gimple_range_op_handler. (gori_compute::compute_logical_operands): Ditto. (compute_operand1_range): Ditto. (gori_compute::compute_operand2_range): Ditto. (gori_compute::compute_operand1_and_operand2_range): Ditto. * gimple-range-gori.h: Adjust protoypes. * gimple-range-op.cc: New. Supply gimple_range_op_handler methods. * gimple-range-op.h: New. Supply gimple_range_op_handler class. * gimple-range.cc (gimple_ranger::prefill_name): Use gimple_range_op_handler. (gimple_ranger::prefill_stmt_dependencies): Ditto. * gimple-range.h: Include gimple-range-op.h. * range-op.cc (range_op_handler::range_op_handler): Adjust and remove gimple * parameter option. * range-op.h: Adjust prototypes.
2022-09-18Rewrite NAN and sign handling in frangeAldy Hernandez1-1/+1
The attatched patch rewrites the NAN and sign handling, dropping both tristates in favor of a pair of boolean flags for NANs, and nothing at all for signs. The signs are tracked in the range itself, so now it's possible to describe things like [-0.0, +0.0] +NAN, [+0, +0], [-5, +0], [+0, 3] -NAN, etc. Here is an example of the various ranges and how they are displayed: [frange] float VARYING NAN ;; Varying includes NAN [frange] UNDEFINED ;; Empty set as always [frange] float [] +-NAN ;; Unknown sign NAN [frange] float [] -NAN ;; -NAN [frange] float [] +NAN ;; +NAN [frange] float [-0.0, 0.0] ;; All zeros. [frange] float [-0.0, -0.0] +-NAN ;; -0 or NAN. [frange] float [-5.0e+0, -1.0e+0] +NAN ;; [-5, -1] or +NAN [frange] float [-5.0e+0, -0.0] +-NAN ;; [-5, -0] or NAN [frange] float [-5.0e+0, -0.0] ;; [-5, -0] [frange] float [5.0e+0, 1.0e+1] ;; [5, 10] Notice the NAN signs are decoupled from the range, so we can represent a negative range with a positive NAN. For this range, frange::signbit_p() would return false, as only when the signs of the NANs and range agree can we be certain. There is no longer any pessimization of ranges for intersects involving NANs. Also, union and intersect work with signed zeros: // [-0, x] U [+0, x] => [-0, x] // [ x, -0] U [ x, +0] => [ x, +0] // [-0, x] ^ [+0, x] => [+0, x] // [ x, -0] ^ [ x, +0] => [ x, -0] The special casing for signed zeros in the singleton code is gone in favor of just making sure the signs in the range agree, that is [-0, -0] for example. I have removed the idea that a known NAN is a "range", so a NAN is no longer in the endpoints itself. Requesting the bound of a known NAN is a hard fail. For that matter, we don't store the actual NAN in the range. The only information we have are the set of boolean flags. This way we make sure nothing seeps into the frange. This also means it's explicit that we don't track anything but the sign in NANs. We can revisit this if we desire to track signalling or whatever concoction y'all can imagine. Regstrapped with mpfr tests on x86-64 and ppc64le Linux. Selftests were also run with -ffinite-math-only on x86-64. At Jakub's suggestion, I built lapack with associated tests. They pass on x86-64 and ppc64le Linux with no regressions from mainline. As a sanity check, I also ran them for -ffinite-math-only on x86 which (as expected) returned: NaN arithmetic did not perform per the ieee spec Otherwise, all tests pass for -ffinite-math-only. gcc/ChangeLog: * range-op-float.cc (frange_add_zeros): Replace set_signbit with union of zero. * value-query.cc (range_query::get_tree_range): Remove set_signbit use. * value-range-pretty-print.cc (vrange_printer::print_frange_prop): Remove. (vrange_printer::print_frange_nan): New. * value-range-pretty-print.h (print_frange_prop): Remove. (print_frange_nan): New. * value-range-storage.cc (frange_storage_slot::set_frange): Set kind and NAN fields. (frange_storage_slot::get_frange): Restore kind and NAN fields. * value-range-storage.h (class frange_storage_slot): Add kind and NAN fields. * value-range.cc (frange::update_nan): Remove. (frange::set_signbit): Remove. (frange::set): Adjust for NAN fields. (frange::normalize_kind): Remove m_props. (frange::combine_zeros): New. (frange::union_nans): New. (frange::union_): Handle new NAN fields. (frange::intersect_nans): New. (frange::intersect): Handle new NAN fields. (frange::operator=): Same. (frange::operator==): Same. (frange::contains_p): Same. (frange::singleton_p): Remove special case for signed zeros. (frange::verify_range): Adjust for new NAN fields. (frange::set_zero): Handle signed zeros. (frange::set_nonnegative): Same. (range_tests_nan): Adjust tests. (range_tests_signed_zeros): Same. (range_tests_signbit): Same. (range_tests_floats): Same. * value-range.h (class fp_prop): Remove. (FP_PROP_ACCESSOR): Remove. (class frange_props): Remove (frange::lower_bound): NANs don't have endpoints. (frange::upper_bound): Same. (frange_props::operator==): Remove. (frange_props::union_): Remove. (frange_props::intersect): Remove. (frange::update_nan): New. (frange::clear_nan): New. (frange::undefined_p): New. (frange::set_nan): New. (frange::known_finite): Adjust for new NAN representation. (frange::maybe_isnan): Same. (frange::known_isnan): Same. (frange::signbit_p): Same. * gimple-range-fold.cc (range_of_builtin_int_call): Rename known_signbit_p into signbit_p.
2022-09-08Implement known/maybe fpclassify like API for frange.Aldy Hernandez1-9/+10
gcc/ChangeLog: * gimple-range-fold.cc (fold_using_range::range_of_builtin_int_call): Use fpclassify like API. * range-op-float.cc (finite_operand_p): Same. (finite_operands_p): Same. (foperator_lt::fold_range): Same. (foperator_le::fold_range): Same. (foperator_gt::fold_range): Same. (foperator_ge::fold_range): Same. (foperator_unordered::fold_range): Same. (foperator_unordered::op1_range): Same. (foperator_ordered::fold_range): Same. * value-range.cc (frange::set_nan): Same. (frange::set_signbit): Same. (frange::union_): Same. (frange::intersect): Same. (frange::operator==): Same. (frange::singleton_p): Same. (frange::verify_range): Same. (range_tests_nan): Same. (range_tests_floats): Same. * value-range.h(frange::known_finite): New. (frange::maybe_inf): New. (frange::known_inf): New. (frange::maybe_nan): New. (frange::known_nan): New. (frange::known_signbit): New.
2022-09-05Do not fold __builtin_signbit if NAN is a possibility.Aldy Hernandez1-1/+3
I had some queued up work to try harder to keep the sign bit up to date in the presence of NANs, but after the discussion with Richi regarding the representation of NAN and signs in the frange, I've decided to put it aside until after Cauldron, since it'll probably get rewritten anyhow. So for now, the sign property in the frange is not applicable to NANs. Right now the only user of the sign bit that affects generated code (apart from signed zeros) is __builtin_sign, so I'm just checking for NAN there. Signed zeros continue working as before. Regstrapped and mpfr checked on x86-64 Linux. gcc/ChangeLog: * gimple-range-fold.cc (fold_using_range::range_of_builtin_int_call): Ignore sign bit when there's the possibility of a NAN.
2022-09-05Fold __builtin_signbit to nonzero instead of 1.Aldy Hernandez1-4/+1
After Joseph's comment wrt __builtin_signbit, I have been unable to convince myself that arbitrarily folding __builtin_signbit () of a negative number to 1 is correct. For example, on the true side of x < -5.0 we know the sign bit is set, but on the false side, we know nothing because X may be a NAN. I don't want to put ourselves in a position where the same call to __builtin_signbit can return two different things (1 or negative whatever), so I'm going to return nonzero which is correct across the board until someone can convince me otherwise. Setting the range to nonzero still allows us to fold conditionals checking __fold_builtin, while not actually propagating a 1. Zero propagation still works. That being said, I still think we should be folding __builtin_signbit's of negative numbers to whatever the hardware returns, instead of 1/0 like what the front ends do. gcc/ChangeLog: * gimple-range-fold.cc (fold_using_range::range_of_builtin_int_call): Fold a set signbit in __builtin_signbit to nonzero. gcc/testsuite/ChangeLog: * gcc.dg/tree-ssa/vrp-float-signbit-2.c: New test.
2022-09-01Implement ranger folder for __builtin_signbit.Aldy Hernandez1-0/+20
Now that we keep track of the signbit, we can use it to fold __builtin_signbit. I am assuming I don't have try too hard to get the actual signbit number and 1 will do. Especially, since we're inconsistent in trunk whether we fold the builtin or whether we calculate it at runtime. abulafia:~$ cat a.c float nzero = -0.0; main(){ printf("0x%x\n", __builtin_signbit(-0.0)); printf("0x%x\n", __builtin_signbit(nzero)); } abulafia:~$ gcc a.c -w && ./a.out 0x1 0x80000000 It is amazing that we've been failing to fold something as simple as this: if (x > 5.0) num = __builtin_signbit (x); It does the right thing now :-P. gcc/ChangeLog: * gimple-range-fold.cc (fold_using_range::range_of_builtin_int_call): Add case for CFN_BUILT_IN_SIGNBIT. gcc/testsuite/ChangeLog: * gcc.dg/tree-ssa/vrp-float-signbit-1.c: New test.
2022-08-16Abstract interesting ssa-names from GORI.Andrew MacLeod1-0/+33
Provide a routine to pick out the ssa-names from interesting statements. * gimple-range-fold.cc (gimple_range_ssa_names): New. * gimple-range-fold.h (gimple_range_ssa_names): New prototype. * gimple-range-gori.cc (range_def_chain::get_def_chain): Move code to new routine.
2022-08-02Do not register edges for statements not understood.Andrew MacLeod1-2/+4
Previously, all gimple_cond types were undserstoof, with float values, this is no longer true. We should gracefully do nothing if the gcond type is not supported. PR tree-optimization/106510 gcc/ * gimple-range-fold.cc (fur_source::register_outgoing_edges): Check for unsupported statements early. gcc/testsuite * gcc.dg/pr106510.c: New.
2022-08-02Make range_of_ssa_name_with_loop_info type agnostic.Aldy Hernandez1-11/+35
gcc/ChangeLog: * gimple-range-fold.cc (fold_using_range::range_of_phi): Remove irange check. (tree_lower_bound): New. (tree_upper_bound): New. (fold_using_range::range_of_ssa_name_with_loop_info): Convert to vrange. * gimple-range-fold.h (range_of_ssa_name_with_loop_info): Change argument to vrange.
2022-08-01Make irange dependency explicit for range_of_ssa_name_with_loop_info.Aldy Hernandez1-5/+5
Even though ranger is type agnostic, SCEV seems to only work with integers. This patch removes some FIXME notes making it explicit that bounds_of_var_in_loop only works with iranges. Tested on x86-64 Linux. gcc/ChangeLog: * gimple-range-fold.cc (fold_using_range::range_of_phi): Only query SCEV for integers. (fold_using_range::range_of_ssa_name_with_loop_info): Remove irange check.
2022-07-04Misc conversions to vrange.Aldy Hernandez1-14/+18
The following converts a handful of places that were irange centric. Tested on x86-64 Linux. gcc/ChangeLog: * gimple-range-fold.cc (fold_using_range::range_of_ssa_name_with_loop_info): Restrict the call to SCEV for irange supported types. (fold_using_range::range_of_builtin_int_call): Convert to vrange. * gimple-range.cc (gimple_ranger::prefill_stmt_dependencies): Same. * tree-ssa-dom.cc (cprop_operand): Same.
2022-06-29Don't use gori dependencies to optimize.Andrew MacLeod1-13/+17
The routine fold_using_range::relation_fold_and_or needs to veriyf that both operands of 2 stmts are the same, and uses GORIs dependency cache for this. This cache cannot be counted on to reflect the current contents of a stmt, expecially in the presence of an IL changing pass. Instead, look at the statement operands. PR tree-optimization/106114 gcc/ * gimple-range-fold.cc (fold_using_range::relation_fold_and_or): Check statement operands instead of GORI cache. gcc/testsuite/ * gcc.dg/pr106114.c: New.
2022-06-03Implement vrange::supports_type_p.Aldy Hernandez1-3/+2
[I have conservatively assumed that both the loop-ch and loop-unswitch passes, which also use the ranger, only support integers and pointers. If the goal is to handle other types as well, irange::supports_p() should be Value_Range::supports_type_p(), and any uses of int_range_max should be converted to Value_Range. I can help in the conversion if you'd like.] As discussed, this patch disambiguates the use of supports_type_p throughout, as what ranger supports is a totally different question than what a given range variant (irange, frange, etc) supports. Unfortunately we need both a static method and a virtual method, and they can't be named the same. The uses are documented in the vrange class: +// To query what types ranger and the entire ecosystem can support, +// use Value_Range::supports_type_p(tree type). This is a static +// method available independently of any vrange object. +// +// To query what a given vrange variant can support, use: +// irange::supports_p () +// frange::supports_p () +// etc +// +// To query what a range object can support, use: +// void foo (vrange &v, irange &i, frange &f) +// { +// if (v.supports_type_p (type)) ... +// if (i.supports_type_p (type)) ... +// if (f.supports_type_p (type)) ... +// } The value_range_equiv::supports_p() method can be use to determine what legacy VRP supports, as irange::supports_p() will no longer be applicable in the evrp analyzer code base once irange and prange are split. Tested on x86-64 Linux. gcc/ChangeLog: * gimple-range-edge.cc (gimple_outgoing_range_stmt_p): Adjust for an object level supports_type_p for irange and a static Value_Range::supports_type_p. * gimple-range-fold.cc (fold_using_range::range_of_range_op): Same. (fold_using_range::range_of_address): Same. (fold_using_range::range_of_builtin_call): Same. * gimple-range-fold.h (gimple_range_type): Same. (gimple_range_ssa_p): Same. * gimple-range-path.cc (path_range_query::internal_range_of_expr): Same. (path_range_query::range_of_stmt): Same. (path_range_query::add_to_imports): Same. * gimple-range.cc (gimple_ranger::range_on_edge): Same. (gimple_ranger::export_global_ranges): Same. * gimple-ssa-evrp-analyze.cc (evrp_range_analyzer::record_ranges_from_phis): Same. * range-op.cc (range_operator::wi_fold): Same. (range_operator::fold_range): Same. * tree-ssa-loop-ch.cc (entry_loop_condition_is_static): Same. * tree-ssa-loop-unswitch.cc (struct unswitch_predicate): Same. (evaluate_control_stmt_using_entry_checks): Same. * tree-ssa-threadedge.cc (hybrid_jt_simplifier::compute_ranges_from_state): Same. * tree-vrp.cc (supported_types_p): Same. * value-query.cc (range_query::value_of_expr): Same. (range_query::value_on_edge): Same. (range_query::value_of_stmt): Same. (range_query::get_tree_range): Same. (get_range_global): Same. (global_range_query::range_of_expr): Same. * value-range-equiv.h (class value_range_equiv): Same. * value-range.cc (irange::supports_type_p): Same. (unsupported_range::supports_type_p): Same. * value-range.h (enum value_range_discriminator): Same. (Value_Range::init): Same. (Value_Range::supports_type_p): Same. (irange::supports_type_p): Same. (irange::supports_p): Same. (vrange::supports_type_p): Same. (vrange_allocator::alloc_vrange): Same.
2022-06-01Convert ranger and clients to vrange.Aldy Hernandez1-59/+82
Finally, the meat of the work. Convert ranger and associated clients to vrange. Everything's relatively mechanical given the previous patches. I did include a minor cleanup in the edge code. There's no need to check that the type of the switch is an integer as non-integer switches are invalid. I verified this with an appropriately coded assert. Tested on x86-64 & ppc64le Linux. gcc/ChangeLog: * gimple-range-cache.cc (ssa_block_ranges::dump): Convert to vrange. (sbr_vector::sbr_vector): Same. (sbr_vector::grow): Same. (sbr_vector::set_bb_range): Same. (sbr_vector::get_bb_range): Same. (sbr_sparse_bitmap::sbr_sparse_bitmap): Same. (sbr_sparse_bitmap::set_bb_range): Same. (sbr_sparse_bitmap::get_bb_range): Same. (block_range_cache::set_bb_range): Same. (block_range_cache::get_bb_range): Same. (block_range_cache::dump): Same. (ssa_global_cache::get_global_range): Same. (ssa_global_cache::set_global_range): Same. (ssa_global_cache::clear): Same. (ssa_global_cache::dump): Same. (ranger_cache::get_global_range): Same. (ranger_cache::set_global_range): Same. (ranger_cache::range_of_def): Same. (ranger_cache::entry_range): Same. (ranger_cache::exit_range): Same. (ranger_cache::edge_range): Same. (ranger_cache::range_of_expr): Same. (ranger_cache::range_on_edge): Same. (ranger_cache::block_range): Same. (ranger_cache::propagate_cache): Same. (ranger_cache::fill_block_cache): Same. (ranger_cache::range_from_dom): Same. * gimple-range-cache.h: Same. * gimple-range-edge.cc (gimple_outgoing_range::get_edge_range): Same. (gimple_outgoing_range::switch_edge_range): Same. (gimple_outgoing_range::edge_range_p): Same. * gimple-range-edge.h: Same. * gimple-range-fold.cc (fur_source::get_operand): Same. (fur_source::get_phi_operand): Same. (fur_edge::get_operand): Same. (fur_edge::get_phi_operand): Same. (fur_stmt::get_operand): Same. (fur_stmt::get_phi_operand): Same. (fur_list::fur_list): Same. (fur_list::get_operand): Same. (fur_list::get_phi_operand): Same. (fold_range): Same. (adjust_imagpart_expr): Same. (adjust_realpart_expr): Same. (gimple_range_adjustment): Same. (fold_using_range::fold_stmt): Same. (fold_using_range::range_of_range_op): Same. (fold_using_range::range_of_address): Same. (fold_using_range::range_of_phi): Same. (fold_using_range::range_of_call): Same. (fold_using_range::range_of_builtin_call): Same. (fold_using_range::range_of_builtin_int_call): Same. (fold_using_range::range_of_cond_expr): Same. (fur_source::register_outgoing_edges): Same. * gimple-range-fold.h (fold_range): Same. (gimple_range_type): Same. (gimple_range_ssa_p): Same. * gimple-range-gori.cc (gimple_range_calc_op1): Same. (gimple_range_calc_op2): Same. (gori_compute::compute_operand_range_switch): Same. (gori_compute::compute_operand_range): Same. (gori_compute::logical_combine): Same. (gori_compute::compute_logical_operands): Same. (gori_compute::compute_operand1_range): Same. (gori_compute::compute_operand2_range): Same. (gori_compute::compute_operand1_and_operand2_range): Same. (gori_compute::outgoing_edge_range_p): Same. (gori_compute::condexpr_adjust): Same. * gimple-range-gori.h (gimple_range_calc_op1): Same. (gimple_range_calc_op2): Same. * gimple-range-path.cc (path_range_query::get_cache): Same. (path_range_query::set_cache): Same. (path_range_query::range_on_path_entry): Same. (path_range_query::internal_range_of_expr): Same. (path_range_query::range_of_expr): Same. (path_range_query::ssa_range_in_phi): Same. (path_range_query::range_defined_in_block): Same. (path_range_query::compute_ranges_in_phis): Same. (path_range_query::compute_ranges_in_block): Same. (path_range_query::add_to_imports): Same. (path_range_query::range_of_stmt): Same. * gimple-range-path.h: Same. * gimple-range-infer.cc (gimple_infer_range::add_range): Same. (gimple_infer_range::~side_effect_manager): Same. (gimple_infer_range::get_nonzero): Same. (gimple_infer_range::maybe_adjust_range): Same. (gimple_infer_range::add_range): Same. * gimple-range-infer.h: Same. * gimple-range-tests.cc: Same. * gimple-range-trace.cc (range_tracer::trailer): Same. (debug_seed_ranger): Same. * gimple-range-trace.h: Same. * gimple-range.cc (gimple_ranger::range_of_expr): Same. (gimple_ranger::range_on_entry): Same. (gimple_ranger::range_on_exit): Same. (gimple_ranger::range_on_edge): Same. (gimple_ranger::fold_range_internal): Same. (gimple_ranger::range_of_stmt): Same. (gimple_ranger::prefill_name): Same. (gimple_ranger::prefill_stmt_dependencies): Same. (gimple_ranger::export_global_ranges): Same. (gimple_ranger::dump_bb): Same. * gimple-range.h: Same. * gimple-ssa-warn-access.cc (check_nul_terminated_array): Same. (memmodel_to_uhwi): Same. * tree-ssa-loop-niter.cc (refine_value_range_using_guard): Same. (determine_value_range): Same. (record_nonwrapping_iv): Same. (infer_loop_bounds_from_signedness): Same. (scev_var_range_cant_overflow): Same. * tree-ssa-threadedge.cc (hybrid_jt_simplifier::simplify): Same. * value-query.cc (range_query::range_on_edge): Same. (range_query::range_of_stmt): Same. (range_query::value_of_expr): Same. (range_query::value_on_edge): Same. (range_query::value_of_stmt): Same. (range_query::get_tree_range): Same. (update_global_range): Same. (get_range_global): Same. (gimple_range_global): Same. (global_range_query::range_of_expr): Same. (range_query::query_relation): Same. * value-query.h (gimple_range_global): Same. (update_global_range): Same. * vr-values.cc (vr_values::range_of_expr): Same. (bounds_of_var_in_loop): Same. (simplify_using_ranges::vrp_visit_cond_stmt): Same. * vr-values.h (class vr_values): Same. * tree-ssa-loop-unswitch.cc (unswitch_predicate): Same.
2022-06-01Convert range-op.* to vrange.Aldy Hernandez1-22/+21
This patch provides the infrastructure to make range-ops type agnostic. First, the range_op_handler function has been replaced with an object of the same name. It's coded in such a way to minimize changes to the code base, and to encapsulate the dispatch code. Instead of: range_operator *op = range_op_handler (code, type); if (op) op->fold_range (...); We now do: range_op_handler op (code, type); if (op) op->fold_range (...); I've folded gimple_range_handler into the range_op_handler class, since it's also a query into the range operators. Instead of: range_operator *handler = gimple_range_handler (stmt); We now do: range_op_handler handler (stmt); This all has the added benefit of moving all the dispatch code into an independent class and avoid polluting range_operator (which we'll further split later when frange and prange come live). There's this annoying "using" keyword that's been added to each operator due to hiding rules in C++. The issue is that we will have different virtual versions of fold_range() for each combination of operands. For example: // Traditional binary op on irange's. fold_range (irange &lhs, const irange &op1, const irange &op2); // For POINTER_DIFF_EXPR: fold_range (irange &lhs, const prange &op1, const prange &op2); // Cast from irange to prange. fold_range (prange &lhs, const irange &op1, const irange &op2); Overloading virtuals when there are multiple same named methods causes hidden virtuals warnings from -Woverloaded-virtual, thus the using keyword. An alternative would be to have different names: fold_range_III, fold_range_IPP, fold_range_PII, but that's uglier still. Tested on x86-64 & ppc64le Linux. gcc/ChangeLog: * gimple-range-edge.cc (gimple_outgoing_range_stmt_p): Adjust for vrange and convert range_op_handler function calls to use the identically named object. * gimple-range-fold.cc (gimple_range_operand1): Same. (gimple_range_operand2): Same. (fold_using_range::fold_stmt): Same. (fold_using_range::range_of_range_op): Same. (fold_using_range::range_of_builtin_ubsan_call): Same. (fold_using_range::relation_fold_and_or): Same. (fur_source::register_outgoing_edges): Same. * gimple-range-fold.h (gimple_range_handler): Remove. * gimple-range-gori.cc (gimple_range_calc_op1): Adjust for vrange. (gimple_range_calc_op2): Same. (range_def_chain::get_def_chain): Same. (gori_compute::compute_operand_range): Same. (gori_compute::condexpr_adjust): Same. * gimple-range.cc (gimple_ranger::prefill_name): Same. (gimple_ranger::prefill_stmt_dependencies): Same. * range-op.cc (get_bool_state): Same. (class operator_equal): Add using clause. (class operator_not_equal): Same. (class operator_lt): Same. (class operator_le): Same. (class operator_gt): Same. (class operator_ge): Same. (class operator_plus): Same. (class operator_minus): Same. (class operator_mult): Same. (class operator_exact_divide): Same. (class operator_lshift): Same. (class operator_rshift): Same. (class operator_cast): Same. (class operator_logical_and): Same. (class operator_bitwise_and): Same. (class operator_logical_or): Same. (class operator_bitwise_or): Same. (class operator_bitwise_xor): Same. (class operator_trunc_mod): Same. (class operator_logical_not): Same. (class operator_bitwise_not): Same. (class operator_cst): Same. (class operator_identity): Same. (class operator_unknown): Same. (class operator_abs): Same. (class operator_negate): Same. (class operator_addr_expr): Same. (class pointer_or_operator): Same. (operator_plus::op1_range): Adjust for vrange. (operator_minus::op1_range): Same. (operator_mult::op1_range): Same. (operator_cast::op1_range): Same. (operator_bitwise_not::fold_range): Same. (operator_negate::fold_range): Same. (range_op_handler): Rename to... (get_handler): ...this. (range_op_handler::range_op_handler): New. (range_op_handler::fold_range): New. (range_op_handler::op1_range): New. (range_op_handler::op2_range): New. (range_op_handler::lhs_op1_relation): New. (range_op_handler::lhs_op2_relation): New. (range_op_handler::op1_op2_relation): New. (range_cast): Adjust for vrange. * range-op.h (range_op_handler): Remove function. (range_cast): Adjust for vrange. (class range_op_handler): New. (get_bool_state): Adjust for vrange. (empty_range_varying): Same. (relop_early_resolve): Same. * tree-data-ref.cc (compute_distributive_range): Same. * tree-vrp.cc (get_range_op_handler): Remove. (range_fold_binary_symbolics_p): Use range_op_handler class instead of get_range_op_handler. (range_fold_unary_symbolics_p): Same. (range_fold_binary_expr): Same. (range_fold_unary_expr): Same. * value-query.cc (range_query::get_tree_range): Adjust for vrange.