Hi David, In function `tree_cmp` an invariant [1] is assumed which does not necessarily exist. In case both input trees are finally compared via `strcmp`, then
tree_cmp (t1, t2) == -tree_cmp (t2, t1) does not hold in general, since function `strcmp (x, y)` guarantees only that a negative integer is returned in case x<y or a positive integer in case x>y. Currently this breaks s390x where, for example, for certain inputs x,y `tree_cmp (x, y) == 1` and `tree_cmp (y, x) == -2` hold. The attached patch normalizes the output from `strcmp` to -1, 0, or 1 while using an auxiliary function `sign` (stolen from the Hacker's Delight book ;-)). Bootstrapped and tested on s390x. Any thoughts? Cheers, Stefan [1] https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;a=blob;f=gcc/analyzer/region-model.cc;h=9474c6737d54d68f5b36893903cfa6d19df0efed;hb=HEAD#l1849
diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc index 9474c6737d5..bdd9a97e5f8 100644 --- a/gcc/analyzer/region-model.cc +++ b/gcc/analyzer/region-model.cc @@ -62,6 +62,20 @@ along with GCC; see the file COPYING3. If not see #if ENABLE_ANALYZER +/* Normalize X to either -1, 0, or 1. + + Basically performs the same as + if (x < 0) return -1; + else if (x > 0) return 1; + else return 0; + but in a concise way trying to prevent branches. */ + +static int +sign (int x) +{ + return (x > 0) - (x < 0); +} + /* Dump T to PP in language-independent form, for debugging/logging/dumping purposes. */ @@ -1768,8 +1782,8 @@ tree_cmp (const_tree t1, const_tree t2) if (DECL_P (t1)) { if (DECL_NAME (t1) && DECL_NAME (t2)) - return strcmp (IDENTIFIER_POINTER (DECL_NAME (t1)), - IDENTIFIER_POINTER (DECL_NAME (t2))); + return sign (strcmp (IDENTIFIER_POINTER (DECL_NAME (t1)), + IDENTIFIER_POINTER (DECL_NAME (t2)))); else { if (DECL_NAME (t1)) @@ -1819,8 +1833,8 @@ tree_cmp (const_tree t1, const_tree t2) } case STRING_CST: - return strcmp (TREE_STRING_POINTER (t1), - TREE_STRING_POINTER (t2)); + return sign (strcmp (TREE_STRING_POINTER (t1), + TREE_STRING_POINTER (t2))); default: gcc_unreachable ();