re PR tree-optimization/84478 (pdftex miscompilation on i386)
authorJakub Jelinek <jakub@redhat.com>
Wed, 21 Feb 2018 10:35:46 +0000 (11:35 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 21 Feb 2018 10:35:46 +0000 (11:35 +0100)
PR tree-optimization/84478
* gimple-fold.h (get_range_strlen): Add a bool argument defaulted to
false.
* gimple-fold.c (get_range_strlen): Make minlen const and assume it
can't be NULL.  Change FUZZY from bool to int, for 1 add PHI/COND_EXPR
support which is conservatively correct, for 2 only stay conservative
for maxlen.  Formatting and comment capitalization fixes.  Add STRICT
argument to the 2 argument get_range_strlen, adjust 6 arg
get_range_strlen caller and clear minmaxlen[0] and [1] if it returned
false.
(get_maxval_strlen): Adjust 6 arg get_range_strlen caller.
(gimple_fold_builtin_strlen): Pass true as last argument to
get_range_strlen.

* gcc.c-torture/execute/pr84478.c: New test.

Co-Authored-By: Martin Sebor <msebor@redhat.com>
From-SVN: r257870

gcc/ChangeLog
gcc/gimple-fold.c
gcc/gimple-fold.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/pr84478.c [new file with mode: 0644]

index 8b686d03a14f47855adafcb7227d856a57a341b0..a07661b5d4a59c7146de9bb64c193e61d27ee5b2 100644 (file)
@@ -1,3 +1,20 @@
+2018-02-21  Jakub Jelinek  <jakub@redhat.com>
+           Martin Sebor  <msebor@redhat.com>
+
+       PR tree-optimization/84478
+       * gimple-fold.h (get_range_strlen): Add a bool argument defaulted to
+       false.
+       * gimple-fold.c (get_range_strlen): Make minlen const and assume it
+       can't be NULL.  Change FUZZY from bool to int, for 1 add PHI/COND_EXPR
+       support which is conservatively correct, for 2 only stay conservative
+       for maxlen.  Formatting and comment capitalization fixes.  Add STRICT
+       argument to the 2 argument get_range_strlen, adjust 6 arg
+       get_range_strlen caller and clear minmaxlen[0] and [1] if it returned
+       false.
+       (get_maxval_strlen): Adjust 6 arg get_range_strlen caller.
+       (gimple_fold_builtin_strlen): Pass true as last argument to
+       get_range_strlen.
+
 2018-02-20  Martin Sebor  <msebor@redhat.com>
 
        PR middle-end/84095
index c9dad6f42d13638995db9019a0861cc7501b811a..0b7553160b53036b119ffbaa6beb974d99e1eee6 100644 (file)
@@ -1283,13 +1283,16 @@ gimple_fold_builtin_memset (gimple_stmt_iterator *gsi, tree c, tree len)
    value of ARG in LENGTH[0] and LENGTH[1], respectively.
    If ARG is an SSA name variable, follow its use-def chains.  When
    TYPE == 0, if LENGTH[1] is not equal to the length we determine or
-   if we are unable to determine the length or value, return False.
+   if we are unable to determine the length or value, return false.
    VISITED is a bitmap of visited variables.
    TYPE is 0 if string length should be obtained, 1 for maximum string
    length and 2 for maximum value ARG can have.
-   When FUZZY is set and the length of a string cannot be determined,
+   When FUZZY is non-zero and the length of a string cannot be determined,
    the function instead considers as the maximum possible length the
-   size of a character array it may refer to.
+   size of a character array it may refer to.  If FUZZY is 2, it will handle
+   PHIs and COND_EXPRs optimistically, if we can determine string length
+   minimum and maximum, it will use the minimum from the ones where it
+   can be determined.
    Set *FLEXP to true if the range of the string lengths has been
    obtained from the upper bound of an array at the end of a struct.
    Such an array may hold a string that's longer than its upper bound
@@ -1297,14 +1300,13 @@ gimple_fold_builtin_memset (gimple_stmt_iterator *gsi, tree c, tree len)
 
 static bool
 get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
-                 bool fuzzy, bool *flexp)
+                 int fuzzy, bool *flexp)
 {
   tree var, val = NULL_TREE;
   gimple *def_stmt;
 
-  /* The minimum and maximum length.  The MAXLEN pointer stays unchanged
-     but MINLEN may be cleared during the execution of the function.  */
-  tree *minlen = length;
+  /* The minimum and maximum length.  */
+  tree *const minlen = length;
   tree *const maxlen = length + 1;
 
   if (TREE_CODE (arg) != SSA_NAME)
@@ -1445,12 +1447,11 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
       if (!val)
        return false;
 
-      if (minlen
-         && (!*minlen
-             || (type > 0
-                 && TREE_CODE (*minlen) == INTEGER_CST
-                 && TREE_CODE (val) == INTEGER_CST
-                 && tree_int_cst_lt (val, *minlen))))
+      if (!*minlen
+         || (type > 0
+             && TREE_CODE (*minlen) == INTEGER_CST
+             && TREE_CODE (val) == INTEGER_CST
+             && tree_int_cst_lt (val, *minlen)))
        *minlen = val;
 
       if (*maxlen)
@@ -1501,20 +1502,26 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
           }
        else if (gimple_assign_rhs_code (def_stmt) == COND_EXPR)
          {
-           tree op2 = gimple_assign_rhs2 (def_stmt);
-           tree op3 = gimple_assign_rhs3 (def_stmt);
-           return get_range_strlen (op2, length, visited, type, fuzzy, flexp)
-             && get_range_strlen (op3, length, visited, type, fuzzy, flexp);
+           tree ops[2] = { gimple_assign_rhs2 (def_stmt),
+                           gimple_assign_rhs3 (def_stmt) };
+
+           for (unsigned int i = 0; i < 2; i++)
+             if (!get_range_strlen (ops[i], length, visited, type, fuzzy,
+                                    flexp))
+               {
+                 if (fuzzy == 2)
+                   *maxlen = build_all_ones_cst (size_type_node);
+                 else
+                   return false;
+               }
+           return true;
          }
         return false;
 
       case GIMPLE_PHI:
-       {
-         /* All the arguments of the PHI node must have the same constant
-            length.  */
-         unsigned i;
-
-         for (i = 0; i < gimple_phi_num_args (def_stmt); i++)
+       /* All the arguments of the PHI node must have the same constant
+          length.  */
+       for (unsigned i = 0; i < gimple_phi_num_args (def_stmt); i++)
           {
             tree arg = gimple_phi_arg (def_stmt, i)->def;
 
@@ -1529,13 +1536,12 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
 
            if (!get_range_strlen (arg, length, visited, type, fuzzy, flexp))
              {
-               if (fuzzy)
+               if (fuzzy == 2)
                  *maxlen = build_all_ones_cst (size_type_node);
                else
                  return false;
              }
           }
-        }
         return true;
 
       default:
@@ -1549,15 +1555,21 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
    character arrays, use the upper bound of the array as the maximum
    length.  For example, given an expression like 'x ? array : "xyz"'
    and array declared as 'char array[8]', MINMAXLEN[0] will be set
-   to 3 and MINMAXLEN[1] to 7, the longest string that could be
+   to 0 and MINMAXLEN[1] to 7, the longest string that could be
    stored in array.
    Return true if the range of the string lengths has been obtained
    from the upper bound of an array at the end of a struct.  Such
    an array may hold a string that's longer than its upper bound
-   due to it being used as a poor-man's flexible array member.  */
+   due to it being used as a poor-man's flexible array member.
+
+   STRICT is true if it will handle PHIs and COND_EXPRs conservatively
+   and false if PHIs and COND_EXPRs are to be handled optimistically,
+   if we can determine string length minimum and maximum; it will use
+   the minimum from the ones where it can be determined.
+   STRICT false should be only used for warning code.  */
 
 bool
-get_range_strlen (tree arg, tree minmaxlen[2])
+get_range_strlen (tree arg, tree minmaxlen[2], bool strict)
 {
   bitmap visited = NULL;
 
@@ -1565,7 +1577,12 @@ get_range_strlen (tree arg, tree minmaxlen[2])
   minmaxlen[1] = NULL_TREE;
 
   bool flexarray = false;
-  get_range_strlen (arg, minmaxlen, &visited, 1, true, &flexarray);
+  if (!get_range_strlen (arg, minmaxlen, &visited, 1, strict ? 1 : 2,
+                        &flexarray))
+    {
+      minmaxlen[0] = NULL_TREE;
+      minmaxlen[1] = NULL_TREE;
+    }
 
   if (visited)
     BITMAP_FREE (visited);
@@ -1580,7 +1597,7 @@ get_maxval_strlen (tree arg, int type)
   tree len[2] = { NULL_TREE, NULL_TREE };
 
   bool dummy;
-  if (!get_range_strlen (arg, len, &visited, type, false, &dummy))
+  if (!get_range_strlen (arg, len, &visited, type, 0, &dummy))
     len[1] = NULL_TREE;
   if (visited)
     BITMAP_FREE (visited);
@@ -3534,7 +3551,7 @@ gimple_fold_builtin_strlen (gimple_stmt_iterator *gsi)
   wide_int maxlen;
 
   tree lenrange[2];
-  if (!get_range_strlen (gimple_call_arg (stmt, 0), lenrange)
+  if (!get_range_strlen (gimple_call_arg (stmt, 0), lenrange, true)
       && lenrange[0] && TREE_CODE (lenrange[0]) == INTEGER_CST
       && lenrange[1] && TREE_CODE (lenrange[1]) == INTEGER_CST)
     {
index 94fa460f4a340a96a5740a4a630ad5220ae6b75c..d0c4044ef46348023b8d44a55e54708e0b095c99 100644 (file)
@@ -25,7 +25,7 @@ along with GCC; see the file COPYING3.  If not see
 extern tree create_tmp_reg_or_ssa_name (tree, gimple *stmt = NULL);
 extern tree canonicalize_constructor_val (tree, tree);
 extern tree get_symbol_constant_value (tree);
-extern bool get_range_strlen (tree, tree[2]);
+extern bool get_range_strlen (tree, tree[2], bool = false);
 extern tree get_maxval_strlen (tree, int);
 extern void gimplify_and_update_call_from_tree (gimple_stmt_iterator *, tree);
 extern bool fold_stmt (gimple_stmt_iterator *);
index 97983a56a58893ee8792c5c4b1341b34e8922025..073acf5e404b390b2718690385ab39b649c46060 100644 (file)
@@ -1,3 +1,8 @@
+2018-02-21  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/84478
+       * gcc.c-torture/execute/pr84478.c: New test.
+
 2018-02-20  Martin Sebor  <msebor@redhat.com>
 
        PR middle-end/84095
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr84478.c b/gcc/testsuite/gcc.c-torture/execute/pr84478.c
new file mode 100644 (file)
index 0000000..6172b1a
--- /dev/null
@@ -0,0 +1,49 @@
+/* PR tree-optimization/84478 */
+
+long poolptr;
+unsigned char *strpool;
+static const char *poolfilearr[] = {
+  "mu",
+  "",
+#define A "x",
+#define B A "xx", A A "xxx", A A A A A
+#define C B B B B B B B B B B
+#define D C C C C C C C C C C
+  D C C C C C C C B B B
+ ((void *)0) 
+};
+
+__attribute__((noipa)) long
+makestring (void)
+{
+  return 1;
+}
+
+__attribute__((noipa)) long
+loadpoolstrings (long spare_size)
+{
+  const char *s;
+  long g = 0;
+  int i = 0, j = 0;
+  while ((s = poolfilearr[j++]))
+    {
+      int l = __builtin_strlen (s);
+      i += l;
+      if (i >= spare_size) return 0;
+      while (l-- > 0) strpool[poolptr++] = *s++;
+      g = makestring ();
+    }
+  return g;
+}
+
+int
+main ()
+{
+  strpool = __builtin_malloc (4000);
+  if (!strpool)
+    return 0;
+  asm volatile ("" : : : "memory");
+  volatile int r = loadpoolstrings (4000);
+  __builtin_free (strpool);
+  return 0;
+}