@@ -16,6 +16,7 @@ use smallvec::SmallVec;
16
16
use rustc_data_structures:: sync:: { Lrc , Lock } ;
17
17
use std:: env;
18
18
use std:: hash:: Hash ;
19
+ use std:: mem;
19
20
use ty:: { self , TyCtxt } ;
20
21
use util:: common:: { ProfileQueriesMsg , profq_msg} ;
21
22
@@ -208,8 +209,7 @@ impl DepGraph {
208
209
self . with_task_impl ( key, cx, arg, false , task,
209
210
|key| OpenTask :: Regular ( Lock :: new ( RegularOpenTask {
210
211
node : key,
211
- reads : SmallVec :: new ( ) ,
212
- read_set : Default :: default ( ) ,
212
+ read_set : OrderedDepIndexSet :: new ( ) ,
213
213
} ) ) ,
214
214
|data, key, task| data. borrow_mut ( ) . complete_task ( key, task) )
215
215
}
@@ -352,8 +352,7 @@ impl DepGraph {
352
352
if let Some ( ref data) = self . data {
353
353
let ( result, open_task) = ty:: tls:: with_context ( |icx| {
354
354
let task = OpenTask :: Anon ( Lock :: new ( AnonOpenTask {
355
- reads : SmallVec :: new ( ) ,
356
- read_set : Default :: default ( ) ,
355
+ read_set : OrderedDepIndexSet :: new ( ) ,
357
356
} ) ) ;
358
357
359
358
let r = {
@@ -949,8 +948,7 @@ impl CurrentDepGraph {
949
948
if let OpenTask :: Regular ( task) = task {
950
949
let RegularOpenTask {
951
950
node,
952
- read_set : _,
953
- reads
951
+ read_set,
954
952
} = task. into_inner ( ) ;
955
953
assert_eq ! ( node, key) ;
956
954
@@ -961,22 +959,22 @@ impl CurrentDepGraph {
961
959
// when called for LOCAL_CRATE) or they depend on a CrateMetadata
962
960
// node.
963
961
if cfg ! ( debug_assertions) {
964
- if node. kind . is_input ( ) && reads. len ( ) > 0 &&
962
+ if node. kind . is_input ( ) && read_set . reads . len ( ) > 0 &&
965
963
// FIXME(mw): Special case for DefSpan until Spans are handled
966
964
// better in general.
967
965
node. kind != DepKind :: DefSpan &&
968
- reads. iter ( ) . any ( |& i| {
966
+ read_set . reads . iter ( ) . any ( |& i| {
969
967
!( self . nodes [ i] . kind == DepKind :: CrateMetadata ||
970
968
self . nodes [ i] . kind == DepKind :: Krate )
971
969
} )
972
970
{
973
971
bug ! ( "Input node {:?} with unexpected reads: {:?}" ,
974
972
node,
975
- reads. iter( ) . map( |& i| self . nodes[ i] ) . collect:: <Vec <_>>( ) )
973
+ read_set . reads. iter( ) . map( |& i| self . nodes[ i] ) . collect:: <Vec <_>>( ) )
976
974
}
977
975
}
978
976
979
- self . alloc_node ( node, reads)
977
+ self . alloc_node ( node, read_set . reads )
980
978
} else {
981
979
bug ! ( "complete_task() - Expected regular task to be popped" )
982
980
}
@@ -985,18 +983,17 @@ impl CurrentDepGraph {
985
983
fn pop_anon_task ( & mut self , kind : DepKind , task : OpenTask ) -> DepNodeIndex {
986
984
if let OpenTask :: Anon ( task) = task {
987
985
let AnonOpenTask {
988
- read_set : _,
989
- reads
986
+ read_set,
990
987
} = task. into_inner ( ) ;
991
988
debug_assert ! ( !kind. is_input( ) ) ;
992
989
993
990
let mut fingerprint = self . anon_id_seed ;
994
991
let mut hasher = StableHasher :: new ( ) ;
995
992
996
- for & read in reads. iter ( ) {
993
+ for & read in read_set . reads . iter ( ) {
997
994
let read_dep_node = self . nodes [ read] ;
998
995
999
- :: std :: mem:: discriminant ( & read_dep_node. kind ) . hash ( & mut hasher) ;
996
+ mem:: discriminant ( & read_dep_node. kind ) . hash ( & mut hasher) ;
1000
997
1001
998
// Fingerprint::combine() is faster than sending Fingerprint
1002
999
// through the StableHasher (at least as long as StableHasher
@@ -1014,7 +1011,7 @@ impl CurrentDepGraph {
1014
1011
if let Some ( & index) = self . node_to_node_index . get ( & target_dep_node) {
1015
1012
index
1016
1013
} else {
1017
- self . alloc_node ( target_dep_node, reads)
1014
+ self . alloc_node ( target_dep_node, read_set . reads )
1018
1015
}
1019
1016
} else {
1020
1017
bug ! ( "pop_anon_task() - Expected anonymous task to be popped" )
@@ -1039,35 +1036,12 @@ impl CurrentDepGraph {
1039
1036
match * icx. task {
1040
1037
OpenTask :: Regular ( ref task) => {
1041
1038
let mut task = task. lock ( ) ;
1042
- let RegularOpenTask {
1043
- ref mut reads,
1044
- ref mut read_set,
1045
- ref node,
1046
- } = * task;
1047
1039
self . total_read_count += 1 ;
1048
1040
1049
- let is_new_entry = if reads. spilled ( ) {
1050
- read_set. insert ( source)
1051
- } else {
1052
- if reads. as_slice ( ) . contains ( & source) {
1053
- false
1054
- } else {
1055
- if reads. inline_size ( ) == reads. len ( ) {
1056
- read_set. reserve ( 16 ) ;
1057
- read_set. extend ( reads. iter ( ) . cloned ( ) ) ;
1058
- read_set. insert ( source) ;
1059
- }
1060
- true
1061
- }
1062
- } ;
1063
-
1064
- if is_new_entry {
1065
- reads. push ( source) ;
1066
- debug_assert ! ( read_set. is_empty( ) ^ reads. spilled( ) ) ;
1067
-
1041
+ if task. read_set . insert ( source) {
1068
1042
if cfg ! ( debug_assertions) {
1069
1043
if let Some ( ref forbidden_edge) = self . forbidden_edge {
1070
- let target = node;
1044
+ let target = & task . node ;
1071
1045
let source = self . nodes [ source] ;
1072
1046
if forbidden_edge. test ( & source, & target) {
1073
1047
bug ! ( "forbidden edge {:?} -> {:?} created" ,
@@ -1081,10 +1055,7 @@ impl CurrentDepGraph {
1081
1055
}
1082
1056
}
1083
1057
OpenTask :: Anon ( ref task) => {
1084
- let mut task = task. lock ( ) ;
1085
- if task. read_set . insert ( source) {
1086
- task. reads . push ( source) ;
1087
- }
1058
+ task. lock ( ) . read_set . insert ( source) ;
1088
1059
}
1089
1060
OpenTask :: Ignore | OpenTask :: EvalAlways { .. } => {
1090
1061
// ignore
@@ -1110,13 +1081,11 @@ impl CurrentDepGraph {
1110
1081
1111
1082
pub struct RegularOpenTask {
1112
1083
node : DepNode ,
1113
- reads : SmallVec < [ DepNodeIndex ; 8 ] > ,
1114
- read_set : FxHashSet < DepNodeIndex > ,
1084
+ read_set : OrderedDepIndexSet ,
1115
1085
}
1116
1086
1117
1087
pub struct AnonOpenTask {
1118
- reads : SmallVec < [ DepNodeIndex ; 8 ] > ,
1119
- read_set : FxHashSet < DepNodeIndex > ,
1088
+ read_set : OrderedDepIndexSet ,
1120
1089
}
1121
1090
1122
1091
pub enum OpenTask {
@@ -1128,6 +1097,87 @@ pub enum OpenTask {
1128
1097
} ,
1129
1098
}
1130
1099
1100
+ struct OrderedDepIndexSet {
1101
+ reads : SmallVec < [ DepNodeIndex ; 8 ] > ,
1102
+ read_set : FxHashSet < DepNodeIndex > ,
1103
+ }
1104
+
1105
+ impl OrderedDepIndexSet {
1106
+ fn new ( ) -> OrderedDepIndexSet {
1107
+ OrderedDepIndexSet {
1108
+ reads : SmallVec :: from_buf_and_len ( [ DepNodeIndex :: INVALID ; 8 ] , 0 ) ,
1109
+ read_set : Default :: default ( ) ,
1110
+ }
1111
+ }
1112
+ }
1113
+
1114
+ cfg_if ! {
1115
+ if #[ cfg( all( any( target_arch = "x86" , target_arch = "x86_64" ) ,
1116
+ target_feature = "sse2" ,
1117
+ not( stage0) ) ) ] {
1118
+ impl OrderedDepIndexSet {
1119
+
1120
+ #[ inline( always) ]
1121
+ fn insert( & mut self , dep_node_index: DepNodeIndex ) -> bool {
1122
+ unsafe {
1123
+ self . insert_impl( dep_node_index)
1124
+ }
1125
+ }
1126
+
1127
+ #[ target_feature( enable = "sse2" ) ]
1128
+ unsafe fn insert_impl( & mut self , dep_node_index: DepNodeIndex ) -> bool {
1129
+ #[ cfg( target_arch = "x86" ) ]
1130
+ use std:: arch:: x86:: * ;
1131
+ #[ cfg( target_arch = "x86_64" ) ]
1132
+ use std:: arch:: x86_64:: * ;
1133
+
1134
+ if self . reads. len( ) <= self . reads. inline_size( ) {
1135
+ debug_assert!( dep_node_index != DepNodeIndex :: INVALID ) ;
1136
+ debug_assert!( mem:: size_of:: <DepNodeIndex >( ) == 4 ) ;
1137
+ debug_assert!( self . reads. capacity( ) == 8 ) ;
1138
+
1139
+ let ptr = self . reads. as_slice( ) . as_ptr( ) as * const __m128i;
1140
+ let data1 = _mm_loadu_si128( ptr) ;
1141
+ let data2 = _mm_loadu_si128( ptr. offset( 1 ) ) ;
1142
+ let cmp = _mm_set1_epi32( dep_node_index. as_u32( ) as i32 ) ;
1143
+
1144
+ if ( _mm_movemask_epi8( _mm_cmpeq_epi32( cmp, data1) ) |
1145
+ _mm_movemask_epi8( _mm_cmpeq_epi32( cmp, data2) ) ) != 0 {
1146
+ // Already contained
1147
+ false
1148
+ } else {
1149
+ self . reads. push( dep_node_index) ;
1150
+
1151
+ if self . reads. len( ) > self . reads. inline_size( ) {
1152
+ self . read_set. extend( self . reads. iter( ) . cloned( ) ) ;
1153
+ }
1154
+ true
1155
+ }
1156
+ } else {
1157
+ if self . read_set. insert( dep_node_index) {
1158
+ self . reads. push( dep_node_index) ;
1159
+ true
1160
+ } else {
1161
+ false
1162
+ }
1163
+ }
1164
+ }
1165
+ }
1166
+ } else {
1167
+ impl OrderedDepIndexSet {
1168
+ #[ inline( always) ]
1169
+ fn insert( & mut self , dep_node_index: DepNodeIndex ) -> bool {
1170
+ if self . read_set. insert( dep_node_index) {
1171
+ self . reads. push( dep_node_index) ;
1172
+ true
1173
+ } else {
1174
+ false
1175
+ }
1176
+ }
1177
+ }
1178
+ }
1179
+ }
1180
+
1131
1181
// A data structure that stores Option<DepNodeColor> values as a contiguous
1132
1182
// array, using one u32 per entry.
1133
1183
struct DepNodeColorMap {
0 commit comments