From 681056ae64c6f8bd4cc67e00cb87b4c7272eec5e Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 18 May 2011 22:39:05 +0200 Subject: [PATCH] re PR c++/49039 (LLVM StringRef miscompilation with -O2) PR tree-optimization/49039 * tree-vrp.c (extract_range_from_binary_expr): For MIN_EXPR <~[a, b], ~[c, d]> and MAX_EXPR <~[a, b], ~[c, d]> return ~[MAX_EXPR , MIN_EXPR ]. * gcc.c-torture/execute/pr49039.c: New test. * gcc.dg/tree-ssa/pr49039.c: New test. * g++.dg/torture/pr49039.C: New test. From-SVN: r173876 --- gcc/ChangeLog | 7 ++ gcc/testsuite/ChangeLog | 7 ++ gcc/testsuite/g++.dg/torture/pr49039.C | 76 +++++++++++++++++++ gcc/testsuite/gcc.c-torture/execute/pr49039.c | 26 +++++++ gcc/testsuite/gcc.dg/tree-ssa/pr49039.c | 31 ++++++++ gcc/tree-vrp.c | 30 +++++--- 6 files changed, 167 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/g++.dg/torture/pr49039.C create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr49039.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr49039.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 624016c4bc0..0850640b837 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2011-05-18 Jakub Jelinek + + PR tree-optimization/49039 + * tree-vrp.c (extract_range_from_binary_expr): For + MIN_EXPR <~[a, b], ~[c, d]> and MAX_EXPR <~[a, b], ~[c, d]> + return ~[MAX_EXPR , MIN_EXPR ]. + 2011-05-18 Tom de Vries PR target/45098 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 111a32251c0..bf4107cc42d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2011-05-18 Jakub Jelinek + + PR tree-optimization/49039 + * gcc.c-torture/execute/pr49039.c: New test. + * gcc.dg/tree-ssa/pr49039.c: New test. + * g++.dg/torture/pr49039.C: New test. + 2011-05-18 Jason Merrill * g++.dg/cpp0x/constexpr-incomplete3.C: New. diff --git a/gcc/testsuite/g++.dg/torture/pr49039.C b/gcc/testsuite/g++.dg/torture/pr49039.C new file mode 100644 index 00000000000..f576cba42d6 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr49039.C @@ -0,0 +1,76 @@ +// PR tree-optimization/49039 +// { dg-do run } + +template +struct pair +{ + T1 first; + T2 second; + pair (const T1 & a, const T2 & b):first (a), second (b) {} +}; + +template +inline pair +make_pair (T1 x, T2 y) +{ + return pair (x, y); +} + +typedef __SIZE_TYPE__ size_t; +struct S +{ + const char *Data; + size_t Length; + static size_t min (size_t a, size_t b) { return a < b ? a : b; } + static size_t max (size_t a, size_t b) { return a > b ? a : b; } + S () :Data (0), Length (0) { } + S (const char *Str) : Data (Str), Length (__builtin_strlen (Str)) {} + S (const char *data, size_t length) : Data (data), Length (length) {} + bool empty () const { return Length == 0; } + size_t size () const { return Length; } + S slice (size_t Start, size_t End) const + { + Start = min (Start, Length); + End = min (max (Start, End), Length); + return S (Data + Start, End - Start); + } + pair split (char Separator) const + { + size_t Idx = find (Separator); + if (Idx == ~size_t (0)) + return make_pair (*this, S ()); + return make_pair (slice (0, Idx), slice (Idx + 1, ~size_t (0))); + } + size_t find (char C, size_t From = 0) const + { + for (size_t i = min (From, Length), e = Length; i != e; ++i) + if (Data[i] == C) + return i; + return ~size_t (0); + } +}; + +void +Test (const char *arg) +{ + S Desc (arg); + while (!Desc.empty ()) + { + pair Split = Desc.split ('-'); + S Token = Split.first; + Desc = Split.second; + if (Token.empty ()) + continue; + Split = Token.split (':'); + S Specifier = Split.first; + if (Specifier.empty ()) + __builtin_abort (); + } +} + +int +main () +{ + Test ("-"); + return 0; +} diff --git a/gcc/testsuite/gcc.c-torture/execute/pr49039.c b/gcc/testsuite/gcc.c-torture/execute/pr49039.c new file mode 100644 index 00000000000..546d114fedc --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr49039.c @@ -0,0 +1,26 @@ +/* PR tree-optimization/49039 */ +extern void abort (void); +int cnt; + +__attribute__((noinline, noclone)) void +foo (unsigned int x, unsigned int y) +{ + unsigned int minv, maxv; + if (x == 1 || y == -2U) + return; + minv = x < y ? x : y; + maxv = x > y ? x : y; + if (minv == 1) + ++cnt; + if (maxv == -2U) + ++cnt; +} + +int +main () +{ + foo (-2U, 1); + if (cnt != 2) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr49039.c b/gcc/testsuite/gcc.dg/tree-ssa/pr49039.c new file mode 100644 index 00000000000..3500dbf2ac9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr49039.c @@ -0,0 +1,31 @@ +/* PR tree-optimization/49039 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +extern void bar (void); + +void +foo (unsigned int x, unsigned int y) +{ + unsigned int minv, maxv; + if (x >= 3 && x <= 6) + return; + if (y >= 5 && y <= 8) + return; + minv = x < y ? x : y; + maxv = x > y ? x : y; + if (minv == 5) + bar (); + if (minv == 6) + bar (); + if (maxv == 5) + bar (); + if (maxv == 6) + bar (); +} + +/* { dg-final { scan-tree-dump "Folding predicate minv_\[0-9\]* == 5 to 0" "vrp1" } } */ +/* { dg-final { scan-tree-dump "Folding predicate minv_\[0-9\]* == 6 to 0" "vrp1" } } */ +/* { dg-final { scan-tree-dump "Folding predicate maxv_\[0-9\]* == 5 to 0" "vrp1" } } */ +/* { dg-final { scan-tree-dump "Folding predicate maxv_\[0-9\]* == 6 to 0" "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index d940336b40d..2d3a6fcad70 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -1,5 +1,5 @@ /* Support routines for Value Range Propagation (VRP). - Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 + Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Diego Novillo . @@ -2358,17 +2358,27 @@ extract_range_from_binary_expr (value_range_t *vr, op0 + op1 == 0, so we cannot claim that the sum is in ~[0,0]. Note that we are guaranteed to have vr0.type == vr1.type at this point. */ - if (code == PLUS_EXPR && vr0.type == VR_ANTI_RANGE) + if (vr0.type == VR_ANTI_RANGE) { - set_value_range_to_varying (vr); - return; + if (code == PLUS_EXPR) + { + set_value_range_to_varying (vr); + return; + } + /* For MIN_EXPR and MAX_EXPR with two VR_ANTI_RANGEs, + the resulting VR_ANTI_RANGE is the same - intersection + of the two ranges. */ + min = vrp_int_const_binop (MAX_EXPR, vr0.min, vr1.min); + max = vrp_int_const_binop (MIN_EXPR, vr0.max, vr1.max); + } + else + { + /* For operations that make the resulting range directly + proportional to the original ranges, apply the operation to + the same end of each range. */ + min = vrp_int_const_binop (code, vr0.min, vr1.min); + max = vrp_int_const_binop (code, vr0.max, vr1.max); } - - /* For operations that make the resulting range directly - proportional to the original ranges, apply the operation to - the same end of each range. */ - min = vrp_int_const_binop (code, vr0.min, vr1.min); - max = vrp_int_const_binop (code, vr0.max, vr1.max); /* If both additions overflowed the range kind is still correct. This happens regularly with subtracting something in unsigned -- 2.30.2