about summary refs log tree commit diff
diff options
context:
space:
mode:
authorkennytm <kennytm@gmail.com>2018-05-23 00:26:15 +0800
committerGitHub <noreply@github.com>2018-05-23 00:26:15 +0800
commit5b67b13d1e3eb657e94bcf974579c576bbbab873 (patch)
tree3dabe44eeff93e9567eb497e5cc6ecd89314ea45
parentbc76e8b029c83f115b369c921d55077e6a5a2ea8 (diff)
parent2ff632484cd8c2e3b123fbf52d9dd39b54a94505 (diff)
downloadrust-5b67b13d1e3eb657e94bcf974579c576bbbab873.tar.gz
rust-5b67b13d1e3eb657e94bcf974579c576bbbab873.zip
Rollup merge of #50932 - nnethercote:seen-Predicates, r=eddyb
Optimize seen Predicate filtering.

This speeds up a few rustc-perf benchmark runs, most notably ones
involving 'coercions', the best by 2%.
-rw-r--r--src/librustc/traits/select.rs21
1 files changed, 18 insertions, 3 deletions
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index c3b5b8e6fb3..7a52a5cbf5a 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -3356,13 +3356,28 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                     predicate: predicate.value
                 }))
         }).collect();
+
         // We are performing deduplication here to avoid exponential blowups
         // (#38528) from happening, but the real cause of the duplication is
         // unknown. What we know is that the deduplication avoids exponential
-        // amount of predicates being propogated when processing deeply nested
+        // amount of predicates being propagated when processing deeply nested
         // types.
-        let mut seen = FxHashSet();
-        predicates.retain(|i| seen.insert(i.clone()));
+        //
+        // This code is hot enough that it's worth avoiding the allocation
+        // required for the FxHashSet when possible. Special-casing lengths 0,
+        // 1 and 2 covers roughly 75--80% of the cases.
+        if predicates.len() <= 1 {
+            // No possibility of duplicates.
+        } else if predicates.len() == 2 {
+            // Only two elements. Drop the second if they are equal.
+            if predicates[0] == predicates[1] {
+                predicates.truncate(1);
+            }
+        } else {
+            // Three or more elements. Use a general deduplication process.
+            let mut seen = FxHashSet();
+            predicates.retain(|i| seen.insert(i.clone()));
+        }
         self.infcx().plug_leaks(skol_map, snapshot, predicates)
     }
 }