From 4d02592b6c80d09c239a2f19b2983a6b498956c0 Mon Sep 17 00:00:00 2001 From: law Date: Tue, 20 Feb 2018 18:52:07 +0000 Subject: PR middle-end/82123 PR tree-optimization/81592 PR middle-end/79257 * gimple-ssa-sprintf.c: Include alloc-pool.h, vr-values.h and gimple-ssa-evrp-analyze.h (class sprintf_dom_walker): Add after_dom_children member function. Add evrp_range_analyzer member. (sprintf_dom_walker::before_dom_children): Call into the EVRP range analyzer as needed. (sprintf_dom_walker::after_dom_children): New member function. * gcc.dg/builtin-unreachable-6.c: Turn off VRP. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@257852 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/gimple-ssa-sprintf.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'gcc/gimple-ssa-sprintf.c') diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c index a2dd54502e8..545f8337c13 100644 --- a/gcc/gimple-ssa-sprintf.c +++ b/gcc/gimple-ssa-sprintf.c @@ -80,6 +80,9 @@ along with GCC; see the file COPYING3. If not see #include "substring-locations.h" #include "diagnostic.h" #include "domwalk.h" +#include "alloc-pool.h" +#include "vr-values.h" +#include "gimple-ssa-evrp-analyze.h" /* The likely worst case value of MB_LEN_MAX for the target, large enough for UTF-8. Ideally, this would be obtained by a target hook if it were @@ -121,10 +124,12 @@ class sprintf_dom_walker : public dom_walker ~sprintf_dom_walker () {} edge before_dom_children (basic_block) FINAL OVERRIDE; + void after_dom_children (basic_block) FINAL OVERRIDE; bool handle_gimple_call (gimple_stmt_iterator *); struct call_info; bool compute_format_length (call_info &, format_result *); + class evrp_range_analyzer evrp_range_analyzer; }; class pass_sprintf_length : public gimple_opt_pass @@ -3456,7 +3461,7 @@ parse_directive (sprintf_dom_walker::call_info &info, bool sprintf_dom_walker::compute_format_length (call_info &info, - format_result *res) + format_result *res) { if (dump_file) { @@ -4012,11 +4017,15 @@ sprintf_dom_walker::handle_gimple_call (gimple_stmt_iterator *gsi) edge sprintf_dom_walker::before_dom_children (basic_block bb) { + evrp_range_analyzer.enter (bb); for (gimple_stmt_iterator si = gsi_start_bb (bb); !gsi_end_p (si); ) { /* Iterate over statements, looking for function calls. */ gimple *stmt = gsi_stmt (si); + /* First record ranges generated by this statement. */ + evrp_range_analyzer.record_ranges_from_stmt (stmt, false); + if (is_gimple_call (stmt) && handle_gimple_call (&si)) /* If handle_gimple_call returns true, the iterator is already pointing to the next statement. */ @@ -4027,6 +4036,12 @@ sprintf_dom_walker::before_dom_children (basic_block bb) return NULL; } +void +sprintf_dom_walker::after_dom_children (basic_block bb) +{ + evrp_range_analyzer.leave (bb); +} + /* Execute the pass for function FUN. */ unsigned int -- cgit v1.2.1 From d1524944bfcb9d3f1002a043cdc8efb123386e1e Mon Sep 17 00:00:00 2001 From: law Date: Tue, 20 Feb 2018 18:53:29 +0000 Subject: PR middle-end/82123 PR tree-optimization/81592 PR middle-end/79257 * gimple-ssa-sprintf.c (sprintf_dom_walker::handle_gimple_call): Query the EVRP range analyzer for range data rather than using global data. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@257853 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/gimple-ssa-sprintf.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'gcc/gimple-ssa-sprintf.c') diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c index 545f8337c13..4b2de6d2aa4 100644 --- a/gcc/gimple-ssa-sprintf.c +++ b/gcc/gimple-ssa-sprintf.c @@ -3903,16 +3903,13 @@ sprintf_dom_walker::handle_gimple_call (gimple_stmt_iterator *gsi) /* Try to determine the range of values of the argument and use the greater of the two at level 1 and the smaller of them at level 2. */ - wide_int min, max; - enum value_range_type range_type - = get_range_info (size, &min, &max); - if (range_type == VR_RANGE) - { - dstsize - = (warn_level < 2 - ? wi::fits_uhwi_p (max) ? max.to_uhwi () : max.to_shwi () - : wi::fits_uhwi_p (min) ? min.to_uhwi () : min.to_shwi ()); - } + value_range *vr = evrp_range_analyzer.get_value_range (size); + if (vr->type == VR_RANGE + && TREE_CODE (vr->min) == INTEGER_CST + && TREE_CODE (vr->max) == INTEGER_CST) + dstsize = (warn_level < 2 + ? TREE_INT_CST_LOW (vr->max) + : TREE_INT_CST_LOW (vr->min)); /* The destination size is not constant. If the function is bounded (e.g., snprintf) a lower bound of zero doesn't -- cgit v1.2.1 From a669405fb46aca23657b17a3593107a14e99c382 Mon Sep 17 00:00:00 2001 From: law Date: Tue, 20 Feb 2018 18:56:01 +0000 Subject: PR middle-end/82123 PR tree-optimization/81592 PR middle-end/79257 * gimple-ssa-sprintf.c (get_int_range): Accept vr_values parameter pass it to children as needed. (struct directive::fmtresult): Similarly. (struct directive::set_width): Similarly. (struct directive::set_precision): Similarly. (format_integer, format_directive, parse_directive): Similarly. (format_none): Accept unnamed vr_values parameter. (format_percent, format_floating, format_character): Similarly. (format_string, format_plain): Similarly. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@257854 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/gimple-ssa-sprintf.c | 72 +++++++++++++++++++++++++++--------------------- 1 file changed, 41 insertions(+), 31 deletions(-) (limited to 'gcc/gimple-ssa-sprintf.c') diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c index 4b2de6d2aa4..54c91320e56 100644 --- a/gcc/gimple-ssa-sprintf.c +++ b/gcc/gimple-ssa-sprintf.c @@ -771,7 +771,8 @@ fmtresult::type_max_digits (tree type, int base) } static bool -get_int_range (tree, HOST_WIDE_INT *, HOST_WIDE_INT *, bool, HOST_WIDE_INT); +get_int_range (tree, HOST_WIDE_INT *, HOST_WIDE_INT *, bool, HOST_WIDE_INT, + class vr_values *vr_values); /* Description of a format directive. A directive is either a plain string or a conversion specification that starts with '%'. */ @@ -806,7 +807,7 @@ struct directive /* Format conversion function that given a directive and an argument returns the formatting result. */ - fmtresult (*fmtfunc) (const directive &, tree); + fmtresult (*fmtfunc) (const directive &, tree, vr_values *); /* Return True when a the format flag CHR has been used. */ bool get_flag (char chr) const @@ -843,9 +844,9 @@ struct directive or 0, whichever is greater. For a non-constant ARG in some range set width to its range adjusting each bound to -1 if it's less. For an indeterminate ARG set width to [0, INT_MAX]. */ - void set_width (tree arg) + void set_width (tree arg, vr_values *vr_values) { - get_int_range (arg, width, width + 1, true, 0); + get_int_range (arg, width, width + 1, true, 0, vr_values); } /* Set both bounds of the precision range to VAL. */ @@ -859,9 +860,9 @@ struct directive or -1 whichever is greater. For a non-constant ARG in some range set precision to its range adjusting each bound to -1 if it's less. For an indeterminate ARG set precision to [-1, INT_MAX]. */ - void set_precision (tree arg) + void set_precision (tree arg, vr_values *vr_values) { - get_int_range (arg, prec, prec + 1, false, -1); + get_int_range (arg, prec, prec + 1, false, -1, vr_values); } /* Return true if both width and precision are known to be @@ -1042,7 +1043,7 @@ struct sprintf_dom_walker::call_info /* Return the result of formatting a no-op directive (such as '%n'). */ static fmtresult -format_none (const directive &, tree) +format_none (const directive &, tree, vr_values *) { fmtresult res (0); return res; @@ -1051,7 +1052,7 @@ format_none (const directive &, tree) /* Return the result of formatting the '%%' directive. */ static fmtresult -format_percent (const directive &, tree) +format_percent (const directive &, tree, vr_values *) { fmtresult res (1); return res; @@ -1108,7 +1109,8 @@ build_intmax_type_nodes (tree *pintmax, tree *puintmax) static bool get_int_range (tree arg, HOST_WIDE_INT *pmin, HOST_WIDE_INT *pmax, - bool absolute, HOST_WIDE_INT negbound) + bool absolute, HOST_WIDE_INT negbound, + class vr_values *vr_values) { /* The type of the result. */ const_tree type = integer_type_node; @@ -1179,7 +1181,8 @@ get_int_range (tree arg, HOST_WIDE_INT *pmin, HOST_WIDE_INT *pmax, /* Handle an argument with an unknown range as if none had been provided. */ if (unknown) - return get_int_range (NULL_TREE, pmin, pmax, absolute, negbound); + return get_int_range (NULL_TREE, pmin, pmax, absolute, + negbound, vr_values); } /* Adjust each bound as specified by ABSOLUTE and NEGBOUND. */ @@ -1264,7 +1267,7 @@ adjust_range_for_overflow (tree dirtype, tree *argmin, tree *argmax) used when the directive argument or its value isn't known. */ static fmtresult -format_integer (const directive &dir, tree arg) +format_integer (const directive &dir, tree arg, vr_values *vr_values) { tree intmax_type_node; tree uintmax_type_node; @@ -1482,7 +1485,7 @@ format_integer (const directive &dir, tree arg) if (code == INTEGER_CST) { arg = gimple_assign_rhs1 (def); - return format_integer (dir, arg); + return format_integer (dir, arg, vr_values); } if (code == NOP_EXPR) @@ -1527,16 +1530,16 @@ format_integer (const directive &dir, tree arg) /* For unsigned conversions/directives or signed when the minimum is positive, use the minimum and maximum to compute the shortest and longest output, respectively. */ - res.range.min = format_integer (dir, argmin).range.min; - res.range.max = format_integer (dir, argmax).range.max; + res.range.min = format_integer (dir, argmin, vr_values).range.min; + res.range.max = format_integer (dir, argmax, vr_values).range.max; } else if (tree_int_cst_sgn (argmax) < 0) { /* For signed conversions/directives if maximum is negative, use the minimum as the longest output and maximum as the shortest output. */ - res.range.min = format_integer (dir, argmax).range.min; - res.range.max = format_integer (dir, argmin).range.max; + res.range.min = format_integer (dir, argmax, vr_values).range.min; + res.range.max = format_integer (dir, argmin, vr_values).range.max; } else { @@ -1544,9 +1547,12 @@ format_integer (const directive &dir, tree arg) as the shortest output and for the longest output compute the length of the output of both minimum and maximum and pick the longer. */ - unsigned HOST_WIDE_INT max1 = format_integer (dir, argmin).range.max; - unsigned HOST_WIDE_INT max2 = format_integer (dir, argmax).range.max; - res.range.min = format_integer (dir, integer_zero_node).range.min; + unsigned HOST_WIDE_INT max1 + = format_integer (dir, argmin, vr_values).range.max; + unsigned HOST_WIDE_INT max2 + = format_integer (dir, argmax, vr_values).range.max; + res.range.min + = format_integer (dir, integer_zero_node, vr_values).range.min; res.range.max = MAX (max1, max2); } @@ -1887,7 +1893,7 @@ format_floating (const directive &dir, const HOST_WIDE_INT prec[2]) ARG. */ static fmtresult -format_floating (const directive &dir, tree arg) +format_floating (const directive &dir, tree arg, vr_values *) { HOST_WIDE_INT prec[] = { dir.prec[0], dir.prec[1] }; tree type = (dir.modifier == FMT_LEN_L || dir.modifier == FMT_LEN_ll @@ -2127,7 +2133,7 @@ get_string_length (tree str) vsprinf). */ static fmtresult -format_character (const directive &dir, tree arg) +format_character (const directive &dir, tree arg, vr_values *vr_values) { fmtresult res; @@ -2139,7 +2145,7 @@ format_character (const directive &dir, tree arg) res.range.min = 0; HOST_WIDE_INT min, max; - if (get_int_range (arg, &min, &max, false, 0)) + if (get_int_range (arg, &min, &max, false, 0, vr_values)) { if (min == 0 && max == 0) { @@ -2192,7 +2198,7 @@ format_character (const directive &dir, tree arg) vsprinf). */ static fmtresult -format_string (const directive &dir, tree arg) +format_string (const directive &dir, tree arg, vr_values *) { fmtresult res; @@ -2353,7 +2359,7 @@ format_string (const directive &dir, tree arg) /* Format plain string (part of the format string itself). */ static fmtresult -format_plain (const directive &dir, tree) +format_plain (const directive &dir, tree, vr_values *) { fmtresult res (dir.len); return res; @@ -2734,7 +2740,8 @@ maybe_warn (substring_loc &dirloc, location_t argloc, static bool format_directive (const sprintf_dom_walker::call_info &info, - format_result *res, const directive &dir) + format_result *res, const directive &dir, + class vr_values *vr_values) { /* Offset of the beginning of the directive from the beginning of the format string. */ @@ -2759,7 +2766,7 @@ format_directive (const sprintf_dom_walker::call_info &info, return false; /* Compute the range of lengths of the formatted output. */ - fmtresult fmtres = dir.fmtfunc (dir, dir.arg); + fmtresult fmtres = dir.fmtfunc (dir, dir.arg, vr_values); /* Record whether the output of all directives is known to be bounded by some maximum, implying that their arguments are @@ -3025,7 +3032,8 @@ format_directive (const sprintf_dom_walker::call_info &info, static size_t parse_directive (sprintf_dom_walker::call_info &info, directive &dir, format_result *res, - const char *str, unsigned *argno) + const char *str, unsigned *argno, + vr_values *vr_values) { const char *pcnt = strchr (str, target_percent); dir.beg = str; @@ -3343,7 +3351,7 @@ parse_directive (sprintf_dom_walker::call_info &info, if (star_width) { if (INTEGRAL_TYPE_P (TREE_TYPE (star_width))) - dir.set_width (star_width); + dir.set_width (star_width, vr_values); else { /* Width specified by a va_list takes on the range [0, -INT_MIN] @@ -3376,7 +3384,7 @@ parse_directive (sprintf_dom_walker::call_info &info, if (star_precision) { if (INTEGRAL_TYPE_P (TREE_TYPE (star_precision))) - dir.set_precision (star_precision); + dir.set_precision (star_precision, vr_values); else { /* Precision specified by a va_list takes on the range [-1, INT_MAX] @@ -3498,10 +3506,12 @@ sprintf_dom_walker::compute_format_length (call_info &info, directive dir = directive (); dir.dirno = dirno; - size_t n = parse_directive (info, dir, res, pf, &argno); + size_t n = parse_directive (info, dir, res, pf, &argno, + evrp_range_analyzer.get_vr_values ()); /* Return failure if the format function fails. */ - if (!format_directive (info, res, dir)) + if (!format_directive (info, res, dir, + evrp_range_analyzer.get_vr_values ())) return false; /* Return success the directive is zero bytes long and it's -- cgit v1.2.1 From 3a06a652f31f0cccf1e8dadab0edb0ccf9b2b95b Mon Sep 17 00:00:00 2001 From: law Date: Tue, 20 Feb 2018 18:56:56 +0000 Subject: PR middle-end/82123 PR tree-optimization/81592 PR middle-end/79257 * gimple-ssa-sprintf.c (get_int_range): Query EVRP range analyzer for range data rather than using global data. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@257855 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/gimple-ssa-sprintf.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'gcc/gimple-ssa-sprintf.c') diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c index 54c91320e56..b3ffaec3ba6 100644 --- a/gcc/gimple-ssa-sprintf.c +++ b/gcc/gimple-ssa-sprintf.c @@ -1149,9 +1149,10 @@ get_int_range (tree arg, HOST_WIDE_INT *pmin, HOST_WIDE_INT *pmax, && TYPE_PRECISION (argtype) <= TYPE_PRECISION (type)) { /* Try to determine the range of values of the integer argument. */ - wide_int min, max; - enum value_range_type range_type = get_range_info (arg, &min, &max); - if (range_type == VR_RANGE) + value_range *vr = vr_values->get_value_range (arg); + if (vr->type == VR_RANGE + && TREE_CODE (vr->min) == INTEGER_CST + && TREE_CODE (vr->max) == INTEGER_CST) { HOST_WIDE_INT type_min = (TYPE_UNSIGNED (argtype) @@ -1160,8 +1161,8 @@ get_int_range (tree arg, HOST_WIDE_INT *pmin, HOST_WIDE_INT *pmax, HOST_WIDE_INT type_max = tree_to_uhwi (TYPE_MAX_VALUE (argtype)); - *pmin = min.to_shwi (); - *pmax = max.to_shwi (); + *pmin = TREE_INT_CST_LOW (vr->min); + *pmax = TREE_INT_CST_LOW (vr->max); if (*pmin < *pmax) { -- cgit v1.2.1 From 7368576a98593b68a154835be50d632e5e54472b Mon Sep 17 00:00:00 2001 From: law Date: Tue, 20 Feb 2018 18:59:22 +0000 Subject: PR middle-end/82123 PR tree-optimization/81592 PR middle-end/79257 * gimple-ssa-sprintf.c (format_integer): Query EVRP range analyzer for range data rather than using global data. * gcc.dg/pr81592.c: New test. * gcc.dg/pr82123.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@257857 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/gimple-ssa-sprintf.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'gcc/gimple-ssa-sprintf.c') diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c index b3ffaec3ba6..1189d9fea35 100644 --- a/gcc/gimple-ssa-sprintf.c +++ b/gcc/gimple-ssa-sprintf.c @@ -1451,12 +1451,13 @@ format_integer (const directive &dir, tree arg, vr_values *vr_values) { /* Try to determine the range of values of the integer argument (range information is not available for pointers). */ - wide_int min, max; - enum value_range_type range_type = get_range_info (arg, &min, &max); - if (range_type == VR_RANGE) + value_range *vr = vr_values->get_value_range (arg); + if (vr->type == VR_RANGE + && TREE_CODE (vr->min) == INTEGER_CST + && TREE_CODE (vr->max) == INTEGER_CST) { - argmin = wide_int_to_tree (argtype, min); - argmax = wide_int_to_tree (argtype, max); + argmin = vr->min; + argmax = vr->max; /* Set KNOWNRANGE if the argument is in a known subrange of the directive's type and neither width nor precision @@ -1469,11 +1470,12 @@ format_integer (const directive &dir, tree arg, vr_values *vr_values) res.argmin = argmin; res.argmax = argmax; } - else if (range_type == VR_ANTI_RANGE) + else if (vr->type == VR_ANTI_RANGE) { /* Handle anti-ranges if/when bug 71690 is resolved. */ } - else if (range_type == VR_VARYING) + else if (vr->type == VR_VARYING + || vr->type == VR_UNDEFINED) { /* The argument here may be the result of promoting the actual argument to int. Try to determine the type of the actual -- cgit v1.2.1