diff mbox

[4/4] Convert lto streamer out hashing to inchash

Message ID 1405488709-12677-5-git-send-email-andi@firstfloor.org
State New
Headers show

Commit Message

Andi Kleen July 16, 2014, 5:31 a.m. UTC
From: Andi Kleen <ak@linux.intel.com>

No substantial changes, although the hash values will be slightly
different.

gcc/:

2014-07-10  Andi Kleen  <ak@linux.intel.com>

	* lto-streamer-out.c (hash_tree): Convert to inchash.
	(add_flag): New macro.
---
 gcc/lto-streamer-out.c | 245 ++++++++++++++++++++++++++-----------------------
 1 file changed, 129 insertions(+), 116 deletions(-)

Comments

Jeff Law July 23, 2014, 3:40 a.m. UTC | #1
On 07/15/14 23:31, Andi Kleen wrote:
> From: Andi Kleen <ak@linux.intel.com>
>
> No substantial changes, although the hash values will be slightly
> different.
>
> gcc/:
>
> 2014-07-10  Andi Kleen  <ak@linux.intel.com>
>
> 	* lto-streamer-out.c (hash_tree): Convert to inchash.
> 	(add_flag): New macro.
So my question here, does this make any existing LTO objects no longer 
usable?  If so, what, if any policy do we have when we make that kind of 
change?

If existing LTO objects continue to work, then this patch is fine too 
once the explicit begin/end vs ctor/dtor stuff is fixed.


jeff
Richard Biener July 23, 2014, 2:21 p.m. UTC | #2
On Wed, Jul 23, 2014 at 5:40 AM, Jeff Law <law@redhat.com> wrote:
> On 07/15/14 23:31, Andi Kleen wrote:
>>
>> From: Andi Kleen <ak@linux.intel.com>
>>
>> No substantial changes, although the hash values will be slightly
>> different.
>>
>> gcc/:
>>
>> 2014-07-10  Andi Kleen  <ak@linux.intel.com>
>>
>>         * lto-streamer-out.c (hash_tree): Convert to inchash.
>>         (add_flag): New macro.
>
> So my question here, does this make any existing LTO objects no longer
> usable?  If so, what, if any policy do we have when we make that kind of
> change?
>
> If existing LTO objects continue to work, then this patch is fine too once
> the explicit begin/end vs ctor/dtor stuff is fixed.

I'd say add_flag should be in the hash abstraction?  You convert
only some to hash_flag and not all of them - why?  For example
I don't like your handling of TYPE/DECL_MODE.  Please refrain
from doing semantical changes like that and call it a simple
refactoring.

Richard.

>
> jeff
>
>
Andi Kleen July 23, 2014, 2:36 p.m. UTC | #3
On Tue, Jul 22, 2014 at 09:40:15PM -0600, Jeff Law wrote:
> On 07/15/14 23:31, Andi Kleen wrote:
> >From: Andi Kleen <ak@linux.intel.com>
> >
> >No substantial changes, although the hash values will be slightly
> >different.
> >
> >gcc/:
> >
> >2014-07-10  Andi Kleen  <ak@linux.intel.com>
> >
> >	* lto-streamer-out.c (hash_tree): Convert to inchash.
> >	(add_flag): New macro.
> So my question here, does this make any existing LTO objects no longer
> usable?  If so, what, if any policy do we have when we make that kind of
> change?

It breaks the format because a few type hashes change

But breaks happen all the time during development. Currently just adding
a new command option breaks the format. Or pretty much any change to
gimple.

Generally in my experience LTO object files don't stay usable more
than a few days in phase 1.

Currently the format is even broken for patch level releases, usually
due to some option change.

The policy is just that for a given release that is unchanged the 
object format stays compatible.

I submitted some patches to improve this slightly for the options, 
but they were not accepted because of all the other issues.
https://gcc.gnu.org/ml/gcc-patches/2010-10/msg00099.html

Given that reality I assume the patch is ok for you?

-Andi

ak@linux.intel.com -- Speaking for myself only
Jan Hubicka July 23, 2014, 2:53 p.m. UTC | #4
> On 07/15/14 23:31, Andi Kleen wrote:
> >From: Andi Kleen <ak@linux.intel.com>
> >
> >No substantial changes, although the hash values will be slightly
> >different.
> >
> >gcc/:
> >
> >2014-07-10  Andi Kleen  <ak@linux.intel.com>
> >
> >	* lto-streamer-out.c (hash_tree): Convert to inchash.
> >	(add_flag): New macro.
> So my question here, does this make any existing LTO objects no
> longer usable?  If so, what, if any policy do we have when we make
> that kind of change?

We are freely breaking LTO objects all the time and have version checks
that are bumped after each release. If you mix object files from released
versions you get correct diagnostics, if you mix object files from different
versions of trunk, you get random errors or ICEs.  I think we managed to
stay bytecode compatible for 4.8 release series. (Richi knows better)

Once we get well defined gimple and types, we can get also stable bytecode,
but until that this seems resonable policy.

Honza
> 
> If existing LTO objects continue to work, then this patch is fine
> too once the explicit begin/end vs ctor/dtor stuff is fixed.
> 
> 
> jeff
>
Andi Kleen July 23, 2014, 3:15 p.m. UTC | #5
> I think we managed to
> stay bytecode compatible for 4.8 release series. (Richi knows better)

Nope, fortran options broke it at some point.

-Andi
Jan Hubicka July 23, 2014, 4 p.m. UTC | #6
> > I think we managed to
> > stay bytecode compatible for 4.8 release series. (Richi knows better)
> 
> Nope, fortran options broke it at some point.

Duh, option streaming sucks, another things that ought to be fixed this release cycle...

Honza
Richard Biener July 23, 2014, 4 p.m. UTC | #7
On July 23, 2014 5:15:53 PM CEST, Andi Kleen <andi@firstfloor.org> wrote:
>> I think we managed to
>> stay bytecode compatible for 4.8 release series. (Richi knows better)
>
>Nope, fortran options broke it at some point.

We try hard to not break things on branches or at least should bump the version if we do.  Maybe we need some mostly trivial bytecode test cases for branches...

Richard.

>-Andi
Andi Kleen July 23, 2014, 4:06 p.m. UTC | #8
On Wed, Jul 23, 2014 at 06:00:35PM +0200, Richard Biener wrote:
> On July 23, 2014 5:15:53 PM CEST, Andi Kleen <andi@firstfloor.org> wrote:
> >> I think we managed to
> >> stay bytecode compatible for 4.8 release series. (Richi knows better)
> >
> >Nope, fortran options broke it at some point.
> 
> We try hard to not break things on branches or at least should bump the version if we do.  Maybe we need some mostly trivial bytecode test cases for branches...

This patch would have caught that case:

https://gcc.gnu.org/ml/gcc-patches/2010-10/msg00099.html

-Andi
Andi Kleen July 23, 2014, 4:40 p.m. UTC | #9
On Wed, Jul 23, 2014 at 04:21:59PM +0200, Richard Biener wrote:
> On Wed, Jul 23, 2014 at 5:40 AM, Jeff Law <law@redhat.com> wrote:
> > On 07/15/14 23:31, Andi Kleen wrote:
> >>
> >> From: Andi Kleen <ak@linux.intel.com>
> >>
> >> No substantial changes, although the hash values will be slightly
> >> different.
> >>
> >> gcc/:
> >>
> >> 2014-07-10  Andi Kleen  <ak@linux.intel.com>
> >>
> >>         * lto-streamer-out.c (hash_tree): Convert to inchash.
> >>         (add_flag): New macro.
> >
> > So my question here, does this make any existing LTO objects no longer
> > usable?  If so, what, if any policy do we have when we make that kind of
> > change?
> >
> > If existing LTO objects continue to work, then this patch is fine too once
> > the explicit begin/end vs ctor/dtor stuff is fixed.
> 
> I'd say add_flag should be in the hash abstraction?  You convert
> only some to hash_flag and not all of them - why? 

I'll do all.

> For example
> I don't like your handling of TYPE/DECL_MODE.  Please refrain
> from doing semantical changes like that and call it a simple
> refactoring.

Ok. I'll drop it.

Is it ok with those changes?
-Andi
diff mbox

Patch

diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index cf2e9a8..e403d58 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -692,207 +692,217 @@  DFS_write_tree_body (struct output_block *ob,
 static hashval_t
 hash_tree (struct streamer_tree_cache_d *cache, tree t)
 {
+  inchash hstate;
+  unsigned extra_bits = 0;
+  hstate.begin ();
+
 #define visit(SIBLING) \
   do { \
     unsigned ix; \
     if (SIBLING && streamer_tree_cache_lookup (cache, SIBLING, &ix)) \
-      v = iterative_hash_hashval_t (streamer_tree_cache_get_hash (cache, ix), v); \
+      hstate.add_int (streamer_tree_cache_get_hash (cache, ix)); \
   } while (0)
+#define add_flag(flag) \
+  do { extra_bits = (extra_bits << 1) | flag; } while (0)
+#define commit_flag() \
+  do { hstate.add_int (extra_bits); extra_bits = 0; } while (0)
 
   /* Hash TS_BASE.  */
   enum tree_code code = TREE_CODE (t);
-  hashval_t v = iterative_hash_host_wide_int (code, 0);
+  hstate.add_int (code);
   if (!TYPE_P (t))
     {
-      v = iterative_hash_host_wide_int (TREE_SIDE_EFFECTS (t)
-					| (TREE_CONSTANT (t) << 1)
-					| (TREE_READONLY (t) << 2)
-					| (TREE_PUBLIC (t) << 3), v);
+      add_flag (TREE_SIDE_EFFECTS (t));
+      add_flag (TREE_CONSTANT (t));
+      add_flag (TREE_READONLY (t));
+      add_flag (TREE_PUBLIC (t));
     }
-  v = iterative_hash_host_wide_int (TREE_ADDRESSABLE (t)
-				    | (TREE_THIS_VOLATILE (t) << 1), v);
+  add_flag (TREE_ADDRESSABLE (t));
+  add_flag (TREE_THIS_VOLATILE (t));
   if (DECL_P (t))
-    v = iterative_hash_host_wide_int (DECL_UNSIGNED (t), v);
+    add_flag (DECL_UNSIGNED (t));
   else if (TYPE_P (t))
-    v = iterative_hash_host_wide_int (TYPE_UNSIGNED (t), v);
+    add_flag (TYPE_UNSIGNED (t));
   if (TYPE_P (t))
-    v = iterative_hash_host_wide_int (TYPE_ARTIFICIAL (t), v);
+    add_flag (TYPE_ARTIFICIAL (t));
   else
-    v = iterative_hash_host_wide_int (TREE_NO_WARNING (t), v);
-  v = iterative_hash_host_wide_int (TREE_NOTHROW (t)
-				    | (TREE_STATIC (t) << 1)
-				    | (TREE_PROTECTED (t) << 2)
-				    | (TREE_DEPRECATED (t) << 3), v);
+    add_flag (TREE_NO_WARNING (t));
+  add_flag (TREE_NOTHROW (t));
+  add_flag (TREE_STATIC (t));
+  add_flag (TREE_PROTECTED (t));
+  add_flag (TREE_DEPRECATED (t));
   if (code != TREE_BINFO)
-    v = iterative_hash_host_wide_int (TREE_PRIVATE (t), v);
+    add_flag (TREE_PRIVATE (t));
   if (TYPE_P (t))
-    v = iterative_hash_host_wide_int (TYPE_SATURATING (t)
-				      | (TYPE_ADDR_SPACE (t) << 1), v);
+    {
+      add_flag (TYPE_SATURATING (t));
+      add_flag (TYPE_ADDR_SPACE (t));
+    }
   else if (code == SSA_NAME)
-    v = iterative_hash_host_wide_int (SSA_NAME_IS_DEFAULT_DEF (t), v);
+    add_flag (SSA_NAME_IS_DEFAULT_DEF (t));
+  commit_flag ();
 
   if (CODE_CONTAINS_STRUCT (code, TS_INT_CST))
     {
       int i;
-      v = iterative_hash_host_wide_int (TREE_INT_CST_NUNITS (t), v);
-      v = iterative_hash_host_wide_int (TREE_INT_CST_EXT_NUNITS (t), v);
+      hstate.add_wide_int (TREE_INT_CST_NUNITS (t));
+      hstate.add_wide_int (TREE_INT_CST_EXT_NUNITS (t));
       for (i = 0; i < TREE_INT_CST_NUNITS (t); i++)
-	v = iterative_hash_host_wide_int (TREE_INT_CST_ELT (t, i), v);
+	hstate.add_wide_int (TREE_INT_CST_ELT (t, i));
     }
 
   if (CODE_CONTAINS_STRUCT (code, TS_REAL_CST))
     {
       REAL_VALUE_TYPE r = TREE_REAL_CST (t);
-      v = iterative_hash_host_wide_int (r.cl, v);
-      v = iterative_hash_host_wide_int (r.decimal
-					| (r.sign << 1)
-					| (r.signalling << 2)
-					| (r.canonical << 3), v);
-      v = iterative_hash_host_wide_int (r.uexp, v);
-      for (unsigned i = 0; i < SIGSZ; ++i)
-	v = iterative_hash_host_wide_int (r.sig[i], v);
+      add_flag (r.cl);
+      add_flag (r.sign);
+      add_flag (r.signalling);
+      add_flag (r.canonical);
+      commit_flag ();
+      hstate.add_int (r.uexp);
+      hstate.add (r.sig, sizeof (r.sig));
     }
 
   if (CODE_CONTAINS_STRUCT (code, TS_FIXED_CST))
     {
       FIXED_VALUE_TYPE f = TREE_FIXED_CST (t);
-      v = iterative_hash_host_wide_int (f.mode, v);
-      v = iterative_hash_host_wide_int (f.data.low, v);
-      v = iterative_hash_host_wide_int (f.data.high, v);
+      hstate.add_int (f.mode);
+      hstate.add_int (f.data.low);
+      hstate.add_int (f.data.high);
     }
 
   if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
     {
-      v = iterative_hash_host_wide_int (DECL_MODE (t), v);
-      v = iterative_hash_host_wide_int (DECL_NONLOCAL (t)
-					| (DECL_VIRTUAL_P (t) << 1)
-					| (DECL_IGNORED_P (t) << 2)
-					| (DECL_ABSTRACT (t) << 3)
-					| (DECL_ARTIFICIAL (t) << 4)
-					| (DECL_USER_ALIGN (t) << 5)
-					| (DECL_PRESERVE_P (t) << 6)
-					| (DECL_EXTERNAL (t) << 7)
-					| (DECL_GIMPLE_REG_P (t) << 8), v);
-      v = iterative_hash_host_wide_int (DECL_ALIGN (t), v);
+      add_flag (DECL_MODE (t));
+      add_flag (DECL_NONLOCAL (t));
+      add_flag (DECL_VIRTUAL_P (t));
+      add_flag (DECL_IGNORED_P (t));
+      add_flag (DECL_ABSTRACT (t));
+      add_flag (DECL_ARTIFICIAL (t));
+      add_flag (DECL_USER_ALIGN (t));
+      add_flag (DECL_PRESERVE_P (t));
+      add_flag (DECL_EXTERNAL (t));
+      add_flag (DECL_GIMPLE_REG_P (t));
+      commit_flag ();
+      hstate.add_int (DECL_ALIGN (t));
       if (code == LABEL_DECL)
 	{
-	  v = iterative_hash_host_wide_int (EH_LANDING_PAD_NR (t), v);
-	  v = iterative_hash_host_wide_int (LABEL_DECL_UID (t), v);
+          hstate.add_int (EH_LANDING_PAD_NR (t));
+	  hstate.add_int (LABEL_DECL_UID (t));
 	}
       else if (code == FIELD_DECL)
 	{
-	  v = iterative_hash_host_wide_int (DECL_PACKED (t)
-					    | (DECL_NONADDRESSABLE_P (t) << 1),
-					    v);
-	  v = iterative_hash_host_wide_int (DECL_OFFSET_ALIGN (t), v);
+	  add_flag (DECL_PACKED (t));
+	  add_flag (DECL_NONADDRESSABLE_P (t));
+	  hstate.add_int (DECL_OFFSET_ALIGN (t));
 	}
       else if (code == VAR_DECL)
 	{
-	  v = iterative_hash_host_wide_int (DECL_HAS_DEBUG_EXPR_P (t)
-					    | (DECL_NONLOCAL_FRAME (t) << 1),
-					    v);
+	  add_flag (DECL_HAS_DEBUG_EXPR_P (t));
+	  add_flag (DECL_NONLOCAL_FRAME (t));
 	}
       if (code == RESULT_DECL
 	  || code == PARM_DECL
 	  || code == VAR_DECL)
 	{
-	  v = iterative_hash_host_wide_int (DECL_BY_REFERENCE (t), v);
+	  add_flag (DECL_BY_REFERENCE (t));
 	  if (code == VAR_DECL
 	      || code == PARM_DECL)
-	    v = iterative_hash_host_wide_int (DECL_HAS_VALUE_EXPR_P (t), v);
+	    add_flag (DECL_HAS_VALUE_EXPR_P (t));
 	}
     }
 
   if (CODE_CONTAINS_STRUCT (code, TS_DECL_WRTL))
-    v = iterative_hash_host_wide_int (DECL_REGISTER (t), v);
+    hstate.add_int (DECL_REGISTER (t));
 
   if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS))
     {
-      v = iterative_hash_host_wide_int ((DECL_COMMON (t))
-					| (DECL_DLLIMPORT_P (t) << 1)
-					| (DECL_WEAK (t) << 2)
-					| (DECL_SEEN_IN_BIND_EXPR_P (t) << 3)
-					| (DECL_COMDAT (t) << 4)
-					| (DECL_VISIBILITY_SPECIFIED (t) << 6),
-					v);
-      v = iterative_hash_host_wide_int (DECL_VISIBILITY (t), v);
+      add_flag (DECL_COMMON (t));
+      add_flag (DECL_DLLIMPORT_P (t));
+      add_flag (DECL_WEAK (t));
+      add_flag (DECL_SEEN_IN_BIND_EXPR_P (t));
+      add_flag (DECL_COMDAT (t));
+      add_flag (DECL_VISIBILITY_SPECIFIED (t));
+      hstate.add_int (DECL_VISIBILITY (t));
       if (code == VAR_DECL)
 	{
 	  /* DECL_IN_TEXT_SECTION is set during final asm output only.  */
-	  v = iterative_hash_host_wide_int (DECL_HARD_REGISTER (t)
-					    | (DECL_IN_CONSTANT_POOL (t) << 1),
-					    v);
+	  add_flag (DECL_HARD_REGISTER (t));
+	  add_flag (DECL_IN_CONSTANT_POOL (t));
 	}
       if (TREE_CODE (t) == FUNCTION_DECL)
-	v = iterative_hash_host_wide_int (DECL_FINAL_P (t)
-					  | (DECL_CXX_CONSTRUCTOR_P (t) << 1)
-					  | (DECL_CXX_DESTRUCTOR_P (t) << 2),
-					  v);
+        {
+	  add_flag (DECL_FINAL_P (t));
+	  add_flag (DECL_CXX_CONSTRUCTOR_P (t));
+	  add_flag (DECL_CXX_DESTRUCTOR_P (t));
+	}
+      commit_flag ();
     }
 
   if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL))
     {
-      v = iterative_hash_host_wide_int (DECL_BUILT_IN_CLASS (t), v);
-      v = iterative_hash_host_wide_int (DECL_STATIC_CONSTRUCTOR (t)
-					| (DECL_STATIC_DESTRUCTOR (t) << 1)
-					| (DECL_UNINLINABLE (t) << 2)
-					| (DECL_POSSIBLY_INLINED (t) << 3)
-					| (DECL_IS_NOVOPS (t) << 4)
-					| (DECL_IS_RETURNS_TWICE (t) << 5)
-					| (DECL_IS_MALLOC (t) << 6)
-					| (DECL_IS_OPERATOR_NEW (t) << 7)
-					| (DECL_DECLARED_INLINE_P (t) << 8)
-					| (DECL_STATIC_CHAIN (t) << 9)
-					| (DECL_NO_INLINE_WARNING_P (t) << 10)
-					| (DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (t) << 11)
-					| (DECL_NO_LIMIT_STACK (t) << 12)
-					| (DECL_DISREGARD_INLINE_LIMITS (t) << 13)
-					| (DECL_PURE_P (t) << 14)
-					| (DECL_LOOPING_CONST_OR_PURE_P (t) << 15), v);
+      hstate.add_int (DECL_BUILT_IN_CLASS (t));
+      hstate.add_int (DECL_STATIC_CONSTRUCTOR (t)
+				| (DECL_STATIC_DESTRUCTOR (t) << 1)
+				| (DECL_UNINLINABLE (t) << 2)
+				| (DECL_POSSIBLY_INLINED (t) << 3)
+				| (DECL_IS_NOVOPS (t) << 4)
+				| (DECL_IS_RETURNS_TWICE (t) << 5)
+				| (DECL_IS_MALLOC (t) << 6)
+				| (DECL_IS_OPERATOR_NEW (t) << 7)
+				| (DECL_DECLARED_INLINE_P (t) << 8)
+				| (DECL_STATIC_CHAIN (t) << 9)
+				| (DECL_NO_INLINE_WARNING_P (t) << 10)
+				| (DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (t) << 11)
+				| (DECL_NO_LIMIT_STACK (t) << 12)
+				| (DECL_DISREGARD_INLINE_LIMITS (t) << 13)
+				| (DECL_PURE_P (t) << 14)
+				| (DECL_LOOPING_CONST_OR_PURE_P (t) << 15));
       if (DECL_BUILT_IN_CLASS (t) != NOT_BUILT_IN)
-	v = iterative_hash_host_wide_int (DECL_FUNCTION_CODE (t), v);
+	hstate.add_int (DECL_FUNCTION_CODE (t));
     }
 
   if (CODE_CONTAINS_STRUCT (code, TS_TYPE_COMMON))
     {
-      v = iterative_hash_host_wide_int (TYPE_MODE (t), v);
-      v = iterative_hash_host_wide_int (TYPE_STRING_FLAG (t)
+      hstate.add_int (TYPE_STRING_FLAG (t)
 					| (TYPE_NO_FORCE_BLK (t) << 1)
 					| (TYPE_NEEDS_CONSTRUCTING (t) << 2)
 					| (TYPE_PACKED (t) << 3)
 					| (TYPE_RESTRICT (t) << 4)
 					| (TYPE_USER_ALIGN (t) << 5)
-					| (TYPE_READONLY (t) << 6), v);
+					| (TYPE_READONLY (t) << 6)
+					| (TYPE_MODE (t) << 7));
       if (RECORD_OR_UNION_TYPE_P (t))
 	{
-	  v = iterative_hash_host_wide_int (TYPE_TRANSPARENT_AGGR (t)
-					    | (TYPE_FINAL_P (t) << 1), v);
+	  add_flag (TYPE_TRANSPARENT_AGGR (t));
+	  add_flag (TYPE_FINAL_P (t));
 	}
       else if (code == ARRAY_TYPE)
-	v = iterative_hash_host_wide_int (TYPE_NONALIASED_COMPONENT (t), v);
-      v = iterative_hash_host_wide_int (TYPE_PRECISION (t), v);
-      v = iterative_hash_host_wide_int (TYPE_ALIGN (t), v);
-      v = iterative_hash_host_wide_int ((TYPE_ALIAS_SET (t) == 0
+	add_flag (TYPE_NONALIASED_COMPONENT (t));
+      commit_flag ();
+      hstate.add_int (TYPE_PRECISION (t));
+      hstate.add_int (TYPE_ALIGN (t));
+      hstate.add_int ((TYPE_ALIAS_SET (t) == 0
 					 || (!in_lto_p
 					     && get_alias_set (t) == 0))
-					? 0 : -1, v);
+					? 0 : -1);
     }
 
   if (CODE_CONTAINS_STRUCT (code, TS_TRANSLATION_UNIT_DECL))
-    v = iterative_hash (TRANSLATION_UNIT_LANGUAGE (t),
-			strlen (TRANSLATION_UNIT_LANGUAGE (t)), v);
+    hstate.add (TRANSLATION_UNIT_LANGUAGE (t),
+			strlen (TRANSLATION_UNIT_LANGUAGE (t)));
 
   if (CODE_CONTAINS_STRUCT (code, TS_TARGET_OPTION))
     gcc_unreachable ();
 
   if (CODE_CONTAINS_STRUCT (code, TS_OPTIMIZATION))
-    v = iterative_hash (t, sizeof (struct cl_optimization), v);
+    hstate.add (t, sizeof (struct cl_optimization));
 
   if (CODE_CONTAINS_STRUCT (code, TS_IDENTIFIER))
-    v = iterative_hash_host_wide_int (IDENTIFIER_HASH_VALUE (t), v);
+    hstate.add_int (IDENTIFIER_HASH_VALUE (t));
 
   if (CODE_CONTAINS_STRUCT (code, TS_STRING))
-    v = iterative_hash (TREE_STRING_POINTER (t), TREE_STRING_LENGTH (t), v);
+    hstate.add (TREE_STRING_POINTER (t), TREE_STRING_LENGTH (t));
 
   if (CODE_CONTAINS_STRUCT (code, TS_TYPED))
     {
@@ -910,7 +920,7 @@  hash_tree (struct streamer_tree_cache_d *cache, tree t)
 	    x = streamer_tree_cache_get_hash (cache, ix);
 	  else
 	    x = hash_tree (cache, TREE_TYPE (t));
-	  v = iterative_hash_hashval_t (x, v);
+	  hstate.add_int (x);
 	}
       else if (code != IDENTIFIER_NODE)
 	visit (TREE_TYPE (t));
@@ -1032,7 +1042,7 @@  hash_tree (struct streamer_tree_cache_d *cache, tree t)
 
   if (CODE_CONTAINS_STRUCT (code, TS_EXP))
     {
-      v = iterative_hash_host_wide_int (TREE_OPERAND_LENGTH (t), v);
+      hstate.add_int (TREE_OPERAND_LENGTH (t));
       for (int i = 0; i < TREE_OPERAND_LENGTH (t); ++i)
 	visit (TREE_OPERAND (t, i));
     }
@@ -1056,7 +1066,7 @@  hash_tree (struct streamer_tree_cache_d *cache, tree t)
     {
       unsigned i;
       tree index, value;
-      v = iterative_hash_host_wide_int (CONSTRUCTOR_NELTS (t), v);
+      hstate.add_int (CONSTRUCTOR_NELTS (t));
       FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), i, index, value)
 	{
 	  visit (index);
@@ -1067,37 +1077,40 @@  hash_tree (struct streamer_tree_cache_d *cache, tree t)
   if (code == OMP_CLAUSE)
     {
       int i;
+      unsigned val;
 
-      v = iterative_hash_host_wide_int (OMP_CLAUSE_CODE (t), v);
+      hstate.add_int (OMP_CLAUSE_CODE (t));
       switch (OMP_CLAUSE_CODE (t))
 	{
 	case OMP_CLAUSE_DEFAULT:
-	  v = iterative_hash_host_wide_int (OMP_CLAUSE_DEFAULT_KIND (t), v);
+	  val = OMP_CLAUSE_DEFAULT_KIND (t);
 	  break;
 	case OMP_CLAUSE_SCHEDULE:
-	  v = iterative_hash_host_wide_int (OMP_CLAUSE_SCHEDULE_KIND (t), v);
+	  val = OMP_CLAUSE_SCHEDULE_KIND (t);
 	  break;
 	case OMP_CLAUSE_DEPEND:
-	  v = iterative_hash_host_wide_int (OMP_CLAUSE_DEPEND_KIND (t), v);
+	  val = OMP_CLAUSE_DEPEND_KIND (t);
 	  break;
 	case OMP_CLAUSE_MAP:
-	  v = iterative_hash_host_wide_int (OMP_CLAUSE_MAP_KIND (t), v);
+	  val = OMP_CLAUSE_MAP_KIND (t);
 	  break;
 	case OMP_CLAUSE_PROC_BIND:
-	  v = iterative_hash_host_wide_int (OMP_CLAUSE_PROC_BIND_KIND (t), v);
+	  val = OMP_CLAUSE_PROC_BIND_KIND (t);
 	  break;
 	case OMP_CLAUSE_REDUCTION:
-	  v = iterative_hash_host_wide_int (OMP_CLAUSE_REDUCTION_CODE (t), v);
+	  val = OMP_CLAUSE_REDUCTION_CODE (t);
 	  break;
 	default:
+	  val = 0;
 	  break;
 	}
+      hstate.add_int (val);
       for (i = 0; i < omp_clause_num_ops[OMP_CLAUSE_CODE (t)]; i++)
 	visit (OMP_CLAUSE_OPERAND (t, i));
       visit (OMP_CLAUSE_CHAIN (t));
     }
 
-  return v;
+  return hstate.end ();
 
 #undef visit
 }