about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2016-08-05 20:14:47 -0400
committerNiko Matsakis <niko@alum.mit.edu>2016-08-09 08:26:06 -0400
commit02a47032dda473e6d8fa9da969bf157c48fba6dd (patch)
treead11a8b80b66e4e6f6b2a0d28e65e643046b5b9e
parent9978cbc8f42247ab75093b355b54e74b3efbcbf8 (diff)
downloadrust-02a47032dda473e6d8fa9da969bf157c48fba6dd.tar.gz
rust-02a47032dda473e6d8fa9da969bf157c48fba6dd.zip
use preds to serialize just what we need
This massively speeds up serialization. It also
seems to produce deterministic metadata hashes
(before I was seeing inconsistent results).

Fixes #35232.
-rw-r--r--src/librustc_incremental/persist/data.rs16
-rw-r--r--src/librustc_incremental/persist/load.rs189
-rw-r--r--src/librustc_incremental/persist/save.rs170
-rw-r--r--src/test/incremental/callee_caller_cross_crate/b.rs1
-rw-r--r--src/test/incremental/dirty_clean.rs1
-rw-r--r--src/test/incremental/hello_world.rs1
-rw-r--r--src/test/incremental/rlib_cross_crate/b.rs2
-rw-r--r--src/test/incremental/spike.rs5
-rw-r--r--src/test/incremental/string_constant.rs1
-rw-r--r--src/test/incremental/struct_add_field.rs1
-rw-r--r--src/test/incremental/struct_change_field_name.rs1
-rw-r--r--src/test/incremental/struct_change_field_type.rs1
-rw-r--r--src/test/incremental/struct_change_field_type_cross_crate/b.rs1
-rw-r--r--src/test/incremental/struct_change_nothing.rs1
-rw-r--r--src/test/incremental/struct_remove_field.rs1
-rw-r--r--src/test/incremental/type_alias_cross_crate/b.rs1
16 files changed, 178 insertions, 215 deletions
diff --git a/src/librustc_incremental/persist/data.rs b/src/librustc_incremental/persist/data.rs
index 95e9a16f29b..12f3ed8ae2b 100644
--- a/src/librustc_incremental/persist/data.rs
+++ b/src/librustc_incremental/persist/data.rs
@@ -19,7 +19,6 @@ use super::directory::DefPathIndex;
 /// Data for use when recompiling the **current crate**.
 #[derive(Debug, RustcEncodable, RustcDecodable)]
 pub struct SerializedDepGraph {
-    pub nodes: Vec<DepNode<DefPathIndex>>,
     pub edges: Vec<SerializedEdge>,
 
     /// These are hashes of two things:
@@ -44,15 +43,22 @@ pub struct SerializedDepGraph {
     pub hashes: Vec<SerializedHash>,
 }
 
+/// Represents a "reduced" dependency edge. Unlike the full dep-graph,
+/// the dep-graph we serialize contains only edges `S -> T` where the
+/// source `S` is something hashable (a HIR node or foreign metadata)
+/// and the target `T` is something significant, like a work-product.
+/// Normally, significant nodes are only those that have saved data on
+/// disk, but in unit-testing the set of significant nodes can be
+/// increased.
 pub type SerializedEdge = (DepNode<DefPathIndex>, DepNode<DefPathIndex>);
 
 #[derive(Debug, RustcEncodable, RustcDecodable)]
 pub struct SerializedHash {
-    /// node being hashed; either a Hir or MetaData variant, in
-    /// practice
-    pub node: DepNode<DefPathIndex>,
+    /// def-id of thing being hashed
+    pub dep_node: DepNode<DefPathIndex>,
 
-    /// the hash itself, computed by `calculate_item_hash`
+    /// the hash as of previous compilation, computed by code in
+    /// `hash` module
     pub hash: u64,
 }
 
diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs
index 793a0466c31..b704af12a6d 100644
--- a/src/librustc_incremental/persist/load.rs
+++ b/src/librustc_incremental/persist/load.rs
@@ -28,7 +28,7 @@ use super::dirty_clean;
 use super::hash::*;
 use super::util::*;
 
-type DirtyNodes = FnvHashSet<DepNode<DefId>>;
+type DirtyNodes = FnvHashSet<DepNode<DefPathIndex>>;
 
 type CleanEdges = Vec<(DepNode<DefId>, DepNode<DefId>)>;
 
@@ -110,145 +110,95 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // Retrace the paths in the directory to find their current location (if any).
     let retraced = directory.retrace(tcx);
 
-    // Compute the set of Hir nodes whose data has changed.
-    let mut dirty_nodes =
-        initial_dirty_nodes(tcx, &serialized_dep_graph.hashes, &retraced);
-
-    debug!("decode_dep_graph: initial dirty_nodes = {:#?}", dirty_nodes);
+    // TODO -- this could be more efficient if we integrated the `DefIdDirectory` and
+    // pred set more deeply
+
+    // Compute the set of Hir nodes whose data has changed or which have been removed.
+    let dirty_raw_source_nodes = dirty_nodes(tcx, &serialized_dep_graph.hashes, &retraced);
+
+    // Create a (maybe smaller) list of
+    let retraced_edges: Vec<_> =
+        serialized_dep_graph.edges.iter()
+                                  .filter_map(|&(ref raw_source_node, ref raw_target_node)| {
+                                      retraced.map(raw_target_node)
+                                              .map(|target_node| (raw_source_node, target_node))
+                                  })
+                                  .collect();
+
+    // Compute which work-products have changed.
+    let mut dirty_target_nodes = FnvHashSet();
+    for &(raw_source_node, ref target_node) in &retraced_edges {
+        if dirty_raw_source_nodes.contains(raw_source_node) {
+            if !dirty_target_nodes.contains(target_node) {
+                dirty_target_nodes.insert(target_node.clone());
+
+                if tcx.sess.opts.debugging_opts.incremental_info {
+                    // It'd be nice to pretty-print these paths better than just
+                    // using the `Debug` impls, but wev.
+                    println!("module {:?} is dirty because {:?} changed or was removed",
+                             target_node,
+                             raw_source_node.map_def(|&index| {
+                                 Some(directory.def_path_string(tcx, index))
+                             }).unwrap());
+                }
+            }
+        }
+    }
 
-    // Find all DepNodes reachable from that core set. This loop
-    // iterates repeatedly over the list of edges whose source is not
-    // known to be dirty (`clean_edges`). If it finds an edge whose
-    // source is dirty, it removes it from that list and adds the
-    // target to `dirty_nodes`. It stops when it reaches a fixed
-    // point.
-    let clean_edges = compute_clean_edges(tcx,
-                                          &directory,
-                                          &serialized_dep_graph.edges,
-                                          &retraced,
-                                          &mut dirty_nodes);
+    // For work-products that are still clean, add their deps into the
+    // graph. This is needed because later we will have to save this
+    // back out again!
+    let dep_graph = tcx.dep_graph.clone();
+    for (raw_source_node, target_node) in retraced_edges {
+        if dirty_target_nodes.contains(&target_node) {
+            continue;
+        }
 
-    // Add synthetic `foo->foo` edges for each clean node `foo` that
-    // we had before. This is sort of a hack to create clean nodes in
-    // the graph, since the existence of a node is a signal that the
-    // work it represents need not be repeated.
-    let clean_nodes =
-        serialized_dep_graph.nodes
-                            .iter()
-                            .filter_map(|node| retraced.map(node))
-                            .filter(|node| !dirty_nodes.contains(node))
-                            .map(|node| (node.clone(), node));
+        let source_node = retraced.map(raw_source_node).unwrap();
 
-    // Add nodes and edges that are not dirty into our main graph.
-    let dep_graph = tcx.dep_graph.clone();
-    for (source, target) in clean_edges.into_iter().chain(clean_nodes) {
-        debug!("decode_dep_graph: clean edge: {:?} -> {:?}", source, target);
+        debug!("decode_dep_graph: clean edge: {:?} -> {:?}", source_node, target_node);
 
-        let _task = dep_graph.in_task(target);
-        dep_graph.read(source);
+        let _task = dep_graph.in_task(target_node);
+        dep_graph.read(source_node);
     }
 
     // Add in work-products that are still clean, and delete those that are
     // dirty.
     let mut work_product_decoder = Decoder::new(work_products_data, 0);
     let work_products = try!(<Vec<SerializedWorkProduct>>::decode(&mut work_product_decoder));
-    reconcile_work_products(tcx, work_products, &dirty_nodes);
+    reconcile_work_products(tcx, work_products, &dirty_target_nodes);
 
     Ok(())
 }
 
-fn initial_dirty_nodes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                 hashes: &[SerializedHash],
-                                 retraced: &RetracedDefIdDirectory)
-                                 -> DirtyNodes {
+/// Computes which of the original set of def-ids are dirty. Stored in
+/// a bit vector where the index is the DefPathIndex.
+fn dirty_nodes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                         hashes: &[SerializedHash],
+                         retraced: &RetracedDefIdDirectory)
+                         -> DirtyNodes {
     let mut hcx = HashContext::new(tcx);
-    let mut items_removed = false;
     let mut dirty_nodes = FnvHashSet();
-    for hash in hashes {
-        match hash.node.map_def(|&i| retraced.def_id(i)) {
-            Some(dep_node) => {
-                let (_, current_hash) = hcx.hash(&dep_node).unwrap();
-                if current_hash != hash.hash {
-                    debug!("initial_dirty_nodes: {:?} is dirty as hash is {:?}, was {:?}",
-                           dep_node.map_def(|&def_id| Some(tcx.def_path(def_id))).unwrap(),
-                           current_hash,
-                           hash.hash);
-                    dirty_nodes.insert(dep_node);
-                }
-            }
-            None => {
-                items_removed = true;
-            }
-        }
-    }
 
-    // If any of the items in the krate have changed, then we consider
-    // the meta-node `Krate` to be dirty, since that means something
-    // which (potentially) read the contents of every single item.
-    if items_removed || !dirty_nodes.is_empty() {
-        dirty_nodes.insert(DepNode::Krate);
-    }
-
-    dirty_nodes
-}
-
-fn compute_clean_edges(tcx: TyCtxt,
-                       directory: &DefIdDirectory,
-                       serialized_edges: &[(SerializedEdge)],
-                       retraced: &RetracedDefIdDirectory,
-                       dirty_nodes: &mut DirtyNodes)
-                       -> CleanEdges {
-    // Build up an initial list of edges. Include an edge (source,
-    // target) if neither node has been removed. If the source has
-    // been removed, add target to the list of dirty nodes.
-    let mut clean_edges = Vec::with_capacity(serialized_edges.len());
-    for &(ref serialized_source, ref serialized_target) in serialized_edges {
-        if let Some(target) = retraced.map(serialized_target) {
-            if let Some(source) = retraced.map(serialized_source) {
-                clean_edges.push((source, target))
-            } else {
-                // source removed, target must be dirty
-                debug!("compute_clean_edges: {:?} dirty because {:?} no longer exists",
-                       target,
-                       serialized_source.map_def(|&index| {
-                           Some(directory.def_path_string(tcx, index))
-                       }).unwrap());
-
-                dirty_nodes.insert(target);
+    for hash in hashes {
+        if let Some(dep_node) = retraced.map(&hash.dep_node) {
+            let (_, current_hash) = hcx.hash(&dep_node).unwrap();
+            if current_hash == hash.hash {
+                continue;
             }
+            debug!("initial_dirty_nodes: {:?} is dirty as hash is {:?}, was {:?}",
+                   dep_node.map_def(|&def_id| Some(tcx.def_path(def_id))).unwrap(),
+                   current_hash,
+                   hash.hash);
         } else {
-            // target removed, ignore the edge
+            debug!("initial_dirty_nodes: {:?} is dirty as it was removed",
+                   hash.dep_node);
         }
-    }
 
-    debug!("compute_clean_edges: dirty_nodes={:#?}", dirty_nodes);
-
-    // Propagate dirty marks by iterating repeatedly over
-    // `clean_edges`. If we find an edge `(source, target)` where
-    // `source` is dirty, add `target` to the list of dirty nodes and
-    // remove it. Keep doing this until we find no more dirty nodes.
-    let mut previous_size = 0;
-    while dirty_nodes.len() > previous_size {
-        debug!("compute_clean_edges: previous_size={}", previous_size);
-        previous_size = dirty_nodes.len();
-        let mut i = 0;
-        while i < clean_edges.len() {
-            if dirty_nodes.contains(&clean_edges[i].0) {
-                let (source, target) = clean_edges.swap_remove(i);
-                debug!("compute_clean_edges: dirty source {:?} -> {:?}",
-                       source, target);
-                dirty_nodes.insert(target);
-            } else if dirty_nodes.contains(&clean_edges[i].1) {
-                let (source, target) = clean_edges.swap_remove(i);
-                debug!("compute_clean_edges: dirty target {:?} -> {:?}",
-                       source, target);
-            } else {
-                i += 1;
-            }
-        }
+        dirty_nodes.insert(hash.dep_node.clone());
     }
 
-    clean_edges
+    dirty_nodes
 }
 
 /// Go through the list of work-products produced in the previous run.
@@ -256,11 +206,10 @@ fn compute_clean_edges(tcx: TyCtxt,
 /// otherwise no longer applicable.
 fn reconcile_work_products<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                      work_products: Vec<SerializedWorkProduct>,
-                                     dirty_nodes: &DirtyNodes) {
+                                     dirty_target_nodes: &FnvHashSet<DepNode<DefId>>) {
     debug!("reconcile_work_products({:?})", work_products);
     for swp in work_products {
-        let dep_node = DepNode::WorkProduct(swp.id.clone());
-        if dirty_nodes.contains(&dep_node) {
+        if dirty_target_nodes.contains(&DepNode::WorkProduct(swp.id.clone())) {
             debug!("reconcile_work_products: dep-node for {:?} is dirty", swp);
             delete_dirty_work_product(tcx, swp);
         } else {
diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs
index e71204dd839..049702a0451 100644
--- a/src/librustc_incremental/persist/save.rs
+++ b/src/librustc_incremental/persist/save.rs
@@ -9,11 +9,12 @@
 // except according to those terms.
 
 use rbml::opaque::Encoder;
-use rustc::dep_graph::{DepGraphQuery, DepNode};
+use rustc::dep_graph::DepNode;
 use rustc::hir::def_id::DefId;
 use rustc::middle::cstore::LOCAL_CRATE;
 use rustc::session::Session;
 use rustc::ty::TyCtxt;
+use rustc_data_structures::fnv::FnvHashMap;
 use rustc_serialize::Encodable as RustcEncodable;
 use std::hash::{Hash, Hasher, SipHasher};
 use std::io::{self, Cursor, Write};
@@ -23,6 +24,7 @@ use std::path::PathBuf;
 use super::data::*;
 use super::directory::*;
 use super::hash::*;
+use super::preds::*;
 use super::util::*;
 
 pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
@@ -35,12 +37,13 @@ pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     let mut hcx = HashContext::new(tcx);
     let mut builder = DefIdDirectoryBuilder::new(tcx);
     let query = tcx.dep_graph.query();
+    let preds = Predecessors::new(&query, &mut hcx);
     save_in(sess,
             dep_graph_path(tcx),
-            |e| encode_dep_graph(&mut hcx, &mut builder, &query, e));
+            |e| encode_dep_graph(&preds, &mut builder, e));
     save_in(sess,
             metadata_hash_path(tcx, LOCAL_CRATE),
-            |e| encode_metadata_hashes(&mut hcx, &mut builder, &query, e));
+            |e| encode_metadata_hashes(tcx, &preds, &mut builder, e));
 }
 
 pub fn save_work_products(sess: &Session, local_crate_name: &str) {
@@ -98,38 +101,37 @@ fn save_in<F>(sess: &Session, opt_path_buf: Option<PathBuf>, encode: F)
     }
 }
 
-pub fn encode_dep_graph<'a, 'tcx>(hcx: &mut HashContext<'a, 'tcx>,
-                                  builder: &mut DefIdDirectoryBuilder,
-                                  query: &DepGraphQuery<DefId>,
-                                  encoder: &mut Encoder)
-                                  -> io::Result<()> {
-    let (nodes, edges) = (query.nodes(), query.edges());
-
-    // Create hashes for inputs.
-    let hashes = nodes.iter()
-        .filter_map(|dep_node| {
-            hcx.hash(dep_node)
-                .map(|(_, hash)| {
-                    let node = builder.map(dep_node);
-                    SerializedHash {
-                        node: node,
-                        hash: hash,
-                    }
-                })
-        })
-        .collect();
+pub fn encode_dep_graph(preds: &Predecessors,
+                        builder: &mut DefIdDirectoryBuilder,
+                        encoder: &mut Encoder)
+                        -> io::Result<()> {
+    // Create a flat list of (Input, WorkProduct) edges for
+    // serialization.
+    let mut edges = vec![];
+    for (&target, sources) in &preds.inputs {
+        match *target {
+            DepNode::MetaData(_) => continue, // see encode_metadata_hashes instead
+            _ => (),
+        }
+        let target = builder.map(target);
+        for &source in sources {
+            let source = builder.map(source);
+            edges.push((source, target.clone()));
+        }
+    }
 
     // Create the serialized dep-graph.
     let graph = SerializedDepGraph {
-        nodes: nodes.iter().map(|node| builder.map(node)).collect(),
-        edges: edges.iter()
-            .map(|&(ref source_node, ref target_node)| {
-                let source = builder.map(source_node);
-                let target = builder.map(target_node);
-                (source, target)
+        edges: edges,
+        hashes: preds.hashes
+            .iter()
+            .map(|(&dep_node, &hash)| {
+                SerializedHash {
+                    dep_node: builder.map(dep_node),
+                    hash: hash,
+                }
             })
             .collect(),
-        hashes: hashes,
     };
 
     debug!("graph = {:#?}", graph);
@@ -141,24 +143,37 @@ pub fn encode_dep_graph<'a, 'tcx>(hcx: &mut HashContext<'a, 'tcx>,
     Ok(())
 }
 
-pub fn encode_metadata_hashes<'a, 'tcx>(hcx: &mut HashContext<'a, 'tcx>,
-                                        builder: &mut DefIdDirectoryBuilder,
-                                        query: &DepGraphQuery<DefId>,
-                                        encoder: &mut Encoder)
-                                        -> io::Result<()> {
-    let tcx = hcx.tcx;
-
-    let serialized_hashes = {
-        // Identify the `MetaData(X)` nodes where `X` is local. These are
-        // the metadata items we export. Downstream crates will want to
-        // see a hash that tells them whether we might have changed the
-        // metadata for a given item since they last compiled.
-        let meta_data_def_ids = query.nodes()
-            .into_iter()
-            .filter_map(|dep_node| match *dep_node {
-                DepNode::MetaData(def_id) if def_id.is_local() => Some(def_id),
-                _ => None,
-            });
+pub fn encode_metadata_hashes(tcx: TyCtxt,
+                              preds: &Predecessors,
+                              builder: &mut DefIdDirectoryBuilder,
+                              encoder: &mut Encoder)
+                              -> io::Result<()> {
+    let mut def_id_hashes = FnvHashMap();
+    let mut def_id_hash = |def_id: DefId| -> u64 {
+        *def_id_hashes.entry(def_id)
+            .or_insert_with(|| {
+                let index = builder.add(def_id);
+                let path = builder.lookup_def_path(index);
+                path.deterministic_hash(tcx)
+            })
+    };
+
+    // For each `MetaData(X)` node where `X` is local, accumulate a
+    // hash.  These are the metadata items we export. Downstream
+    // crates will want to see a hash that tells them whether we might
+    // have changed the metadata for a given item since they last
+    // compiled.
+    //
+    // (I initially wrote this with an iterator, but it seemed harder to read.)
+    let mut serialized_hashes = SerializedMetadataHashes { hashes: vec![] };
+    for (&target, sources) in &preds.inputs {
+        let def_id = match *target {
+            DepNode::MetaData(def_id) => {
+                assert!(def_id.is_local());
+                def_id
+            }
+            _ => continue,
+        };
 
         // To create the hash for each item `X`, we don't hash the raw
         // bytes of the metadata (though in principle we
@@ -166,45 +181,32 @@ pub fn encode_metadata_hashes<'a, 'tcx>(hcx: &mut HashContext<'a, 'tcx>,
         // from the dep-graph. This corresponds to all the inputs that
         // were read to construct the metadata. To create the hash for
         // the metadata, we hash (the hash of) all of those inputs.
-        let hashes = meta_data_def_ids.map(|def_id| {
-            assert!(def_id.is_local());
-            let dep_node = DepNode::MetaData(def_id);
-            let mut state = SipHasher::new();
-            debug!("save: computing metadata hash for {:?}", dep_node);
-
-            let predecessors = query.transitive_predecessors(&dep_node);
-            let mut hashes: Vec<_> = predecessors.iter()
-                .filter_map(|node| hcx.hash(&node))
-                .map(|(def_id, hash)| {
-                    let index = builder.add(def_id);
-                    let path = builder.lookup_def_path(index);
-                    (path.to_string(tcx), hash) // (*)
-                })
-                .collect();
-
-            // (*) creating a `String` from each def-path is a bit inefficient,
-            // but it's the easiest way to get a deterministic ord/hash.
-
-            hashes.sort();
-            state.write_usize(hashes.len());
-            for (path, hash) in hashes {
-                debug!("save: predecessor {:?} has hash {}", path, hash);
-                path.hash(&mut state);
-                state.write_u64(hash.to_le());
-            }
+        debug!("save: computing metadata hash for {:?}", def_id);
+
+        // Create a vector containing a pair of (source-id, hash).
+        // The source-id is stored as a `DepNode<u64>`, where the u64
+        // is the det. hash of the def-path. This is convenient
+        // because we can sort this to get a table ordering across
+        // compilations, even if the def-ids themselves have changed.
+        let mut hashes: Vec<(DepNode<u64>, u64)> = sources.iter()
+            .map(|dep_node| {
+                let hash_dep_node = dep_node.map_def(|&def_id| Some(def_id_hash(def_id))).unwrap();
+                let hash = preds.hashes[dep_node];
+                (hash_dep_node, hash)
+            })
+            .collect();
 
-            let hash = state.finish();
-            debug!("save: metadata hash for {:?} is {}", dep_node, hash);
+        hashes.sort();
+        let mut state = SipHasher::new();
+        hashes.hash(&mut state);
+        let hash = state.finish();
 
-            SerializedMetadataHash {
-                def_index: def_id.index,
-                hash: hash,
-            }
+        debug!("save: metadata hash for {:?} is {}", def_id, hash);
+        serialized_hashes.hashes.push(SerializedMetadataHash {
+            def_index: def_id.index,
+            hash: hash,
         });
-
-        // Collect these up into a vector.
-        SerializedMetadataHashes { hashes: hashes.collect() }
-    };
+    }
 
     // Encode everything.
     try!(serialized_hashes.encode(encoder));
diff --git a/src/test/incremental/callee_caller_cross_crate/b.rs b/src/test/incremental/callee_caller_cross_crate/b.rs
index e81f828beb1..e8b187b5454 100644
--- a/src/test/incremental/callee_caller_cross_crate/b.rs
+++ b/src/test/incremental/callee_caller_cross_crate/b.rs
@@ -10,6 +10,7 @@
 
 // aux-build:a.rs
 // revisions:rpass1 rpass2
+// compile-flags:-Z query-dep-graph
 
 #![feature(rustc_attrs)]
 
diff --git a/src/test/incremental/dirty_clean.rs b/src/test/incremental/dirty_clean.rs
index 9a3097831c5..64b7f2951d2 100644
--- a/src/test/incremental/dirty_clean.rs
+++ b/src/test/incremental/dirty_clean.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // revisions: rpass1 cfail2
+// compile-flags: -Z query-dep-graph
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
diff --git a/src/test/incremental/hello_world.rs b/src/test/incremental/hello_world.rs
index f98ae188bad..a06c25ac055 100644
--- a/src/test/incremental/hello_world.rs
+++ b/src/test/incremental/hello_world.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // revisions: rpass1 rpass2
+// compile-flags: -Z query-dep-graph
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
diff --git a/src/test/incremental/rlib_cross_crate/b.rs b/src/test/incremental/rlib_cross_crate/b.rs
index 55398370425..21b654bdf58 100644
--- a/src/test/incremental/rlib_cross_crate/b.rs
+++ b/src/test/incremental/rlib_cross_crate/b.rs
@@ -16,7 +16,7 @@
 // aux-build:a.rs
 // revisions:rpass1 rpass2 rpass3
 // no-prefer-dynamic
-
+// compile-flags: -Z query-dep-graph
 
 #![feature(rustc_attrs)]
 
diff --git a/src/test/incremental/spike.rs b/src/test/incremental/spike.rs
index 68af20d4191..257699cd3fc 100644
--- a/src/test/incremental/spike.rs
+++ b/src/test/incremental/spike.rs
@@ -35,14 +35,10 @@ mod x {
         X { x: 11, y: 11 }
     }
 
-    #[rustc_dirty(label="TypeckItemBody", cfg="rpass2")]
-    #[rustc_clean(label="ItemSignature", cfg="rpass2")]
     pub fn new() -> X {
         make()
     }
 
-    #[rustc_clean(label="TypeckItemBody", cfg="rpass2")]
-    #[rustc_clean(label="ItemSignature", cfg="rpass2")]
     pub fn sum(x: &X) -> u32 {
         x.x + x.y
     }
@@ -51,7 +47,6 @@ mod x {
 mod y {
     use x;
 
-    #[rustc_clean(label="TypeckItemBody", cfg="rpass2")]
     pub fn assert_sum() -> bool {
         let x = x::new();
         x::sum(&x) == 22
diff --git a/src/test/incremental/string_constant.rs b/src/test/incremental/string_constant.rs
index 0aa728b94dd..f4062169256 100644
--- a/src/test/incremental/string_constant.rs
+++ b/src/test/incremental/string_constant.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // revisions: rpass1 rpass2
+// compile-flags: -Z query-dep-graph
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
diff --git a/src/test/incremental/struct_add_field.rs b/src/test/incremental/struct_add_field.rs
index cc8ef8aedd7..da1b32cd73d 100644
--- a/src/test/incremental/struct_add_field.rs
+++ b/src/test/incremental/struct_add_field.rs
@@ -12,6 +12,7 @@
 // in between revisions (hashing should be stable).
 
 // revisions:rpass1 rpass2
+// compile-flags: -Z query-dep-graph
 
 #![feature(rustc_attrs)]
 
diff --git a/src/test/incremental/struct_change_field_name.rs b/src/test/incremental/struct_change_field_name.rs
index fe29ad66b5f..ba469c62002 100644
--- a/src/test/incremental/struct_change_field_name.rs
+++ b/src/test/incremental/struct_change_field_name.rs
@@ -12,6 +12,7 @@
 // in between revisions (hashing should be stable).
 
 // revisions:rpass1 cfail2
+// compile-flags: -Z query-dep-graph
 
 #![feature(rustc_attrs)]
 
diff --git a/src/test/incremental/struct_change_field_type.rs b/src/test/incremental/struct_change_field_type.rs
index 1a50d515db6..65f3b1b4f36 100644
--- a/src/test/incremental/struct_change_field_type.rs
+++ b/src/test/incremental/struct_change_field_type.rs
@@ -12,6 +12,7 @@
 // in between revisions (hashing should be stable).
 
 // revisions:rpass1 rpass2
+// compile-flags: -Z query-dep-graph
 
 #![feature(rustc_attrs)]
 
diff --git a/src/test/incremental/struct_change_field_type_cross_crate/b.rs b/src/test/incremental/struct_change_field_type_cross_crate/b.rs
index 7a4900d1d9a..95e15d0b7f9 100644
--- a/src/test/incremental/struct_change_field_type_cross_crate/b.rs
+++ b/src/test/incremental/struct_change_field_type_cross_crate/b.rs
@@ -10,6 +10,7 @@
 
 // aux-build:a.rs
 // revisions:rpass1 rpass2
+// compile-flags: -Z query-dep-graph
 
 #![feature(rustc_attrs)]
 
diff --git a/src/test/incremental/struct_change_nothing.rs b/src/test/incremental/struct_change_nothing.rs
index 8095e1ecd84..2bc636153f7 100644
--- a/src/test/incremental/struct_change_nothing.rs
+++ b/src/test/incremental/struct_change_nothing.rs
@@ -12,6 +12,7 @@
 // in between revisions (hashing should be stable).
 
 // revisions:rpass1 rpass2
+// compile-flags: -Z query-dep-graph
 
 #![feature(rustc_attrs)]
 
diff --git a/src/test/incremental/struct_remove_field.rs b/src/test/incremental/struct_remove_field.rs
index ae6399463b8..a7ed79d1a5a 100644
--- a/src/test/incremental/struct_remove_field.rs
+++ b/src/test/incremental/struct_remove_field.rs
@@ -12,6 +12,7 @@
 // in between revisions (hashing should be stable).
 
 // revisions:rpass1 rpass2
+// compile-flags: -Z query-dep-graph
 
 #![feature(rustc_attrs)]
 
diff --git a/src/test/incremental/type_alias_cross_crate/b.rs b/src/test/incremental/type_alias_cross_crate/b.rs
index c5421fcbf5c..09d4db33198 100644
--- a/src/test/incremental/type_alias_cross_crate/b.rs
+++ b/src/test/incremental/type_alias_cross_crate/b.rs
@@ -10,6 +10,7 @@
 
 // aux-build:a.rs
 // revisions:rpass1 rpass2 rpass3
+// compile-flags: -Z query-dep-graph
 
 #![feature(rustc_attrs)]