@@ -30,52 +30,20 @@ use crate::ir::Opcode;
3030/// `finite()` method.) An infinite cost is used to represent a value
3131/// that cannot be computed, or otherwise serve as a sentinel when
3232/// performing search for the lowest-cost representation of a value.
33- #[ derive( Clone , Copy , PartialEq , Eq ) ]
33+ #[ derive( Clone , Copy , PartialEq , Eq , PartialOrd , Ord ) ]
3434pub ( crate ) struct Cost ( u32 ) ;
3535
3636impl core:: fmt:: Debug for Cost {
3737 fn fmt ( & self , f : & mut core:: fmt:: Formatter < ' _ > ) -> core:: fmt:: Result {
3838 if * self == Cost :: infinity ( ) {
3939 write ! ( f, "Cost::Infinite" )
4040 } else {
41- f. debug_struct ( "Cost::Finite" )
42- . field ( "op_cost" , & self . op_cost ( ) )
43- . field ( "depth" , & self . depth ( ) )
44- . finish ( )
41+ f. debug_tuple ( "Cost::Finite" ) . field ( & self . cost ( ) ) . finish ( )
4542 }
4643 }
4744}
4845
49- impl Ord for Cost {
50- #[ inline]
51- fn cmp ( & self , other : & Self ) -> core:: cmp:: Ordering {
52- // We make sure that the high bits are the op cost and the low bits are
53- // the depth. This means that we can use normal integer comparison to
54- // order by op cost and then depth.
55- //
56- // We want to break op cost ties with depth (rather than the other way
57- // around). When the op cost is the same, we prefer shallow and wide
58- // expressions to narrow and deep expressions and breaking ties with
59- // `depth` gives us that. For example, `(a + b) + (c + d)` is preferred
60- // to `((a + b) + c) + d`. This is beneficial because it exposes more
61- // instruction-level parallelism and shortens live ranges.
62- self . 0 . cmp ( & other. 0 )
63- }
64- }
65-
66- impl PartialOrd for Cost {
67- #[ inline]
68- fn partial_cmp ( & self , other : & Self ) -> Option < core:: cmp:: Ordering > {
69- Some ( self . cmp ( other) )
70- }
71- }
72-
7346impl Cost {
74- const DEPTH_BITS : u8 = 8 ;
75- const DEPTH_MASK : u32 = ( 1 << Self :: DEPTH_BITS ) - 1 ;
76- const OP_COST_MASK : u32 = !Self :: DEPTH_MASK ;
77- const MAX_OP_COST : u32 = Self :: OP_COST_MASK >> Self :: DEPTH_BITS ;
78-
7947 pub ( crate ) fn infinity ( ) -> Cost {
8048 // 2^32 - 1 is, uh, pretty close to infinite... (we use `Cost`
8149 // only for heuristics and always saturate so this suffices!)
@@ -86,39 +54,27 @@ impl Cost {
8654 Cost ( 0 )
8755 }
8856
89- /// Construct a new `Cost` from the given parts.
90- ///
91- /// If the opcode cost is greater than or equal to the maximum representable
92- /// opcode cost, then the resulting `Cost` saturates to infinity.
93- fn new ( opcode_cost : u32 , depth : u8 ) -> Cost {
94- if opcode_cost >= Self :: MAX_OP_COST {
95- Self :: infinity ( )
96- } else {
97- Cost ( opcode_cost << Self :: DEPTH_BITS | u32:: from ( depth) )
98- }
99- }
100-
101- fn depth ( & self ) -> u8 {
102- let depth = self . 0 & Self :: DEPTH_MASK ;
103- u8:: try_from ( depth) . unwrap ( )
57+ /// Construct a new `Cost`.
58+ fn new ( cost : u32 ) -> Cost {
59+ Cost ( cost)
10460 }
10561
106- fn op_cost ( & self ) -> u32 {
107- ( self . 0 & Self :: OP_COST_MASK ) >> Self :: DEPTH_BITS
62+ fn cost ( & self ) -> u32 {
63+ self . 0
10864 }
10965
11066 /// Return the cost of an opcode.
11167 fn of_opcode ( op : Opcode ) -> Cost {
11268 match op {
11369 // Constants.
114- Opcode :: Iconst | Opcode :: F32const | Opcode :: F64const => Cost :: new ( 1 , 0 ) ,
70+ Opcode :: Iconst | Opcode :: F32const | Opcode :: F64const => Cost :: new ( 1 ) ,
11571
11672 // Extends/reduces.
11773 Opcode :: Uextend
11874 | Opcode :: Sextend
11975 | Opcode :: Ireduce
12076 | Opcode :: Iconcat
121- | Opcode :: Isplit => Cost :: new ( 1 , 0 ) ,
77+ | Opcode :: Isplit => Cost :: new ( 1 ) ,
12278
12379 // "Simple" arithmetic.
12480 Opcode :: Iadd
@@ -129,27 +85,27 @@ impl Cost {
12985 | Opcode :: Bnot
13086 | Opcode :: Ishl
13187 | Opcode :: Ushr
132- | Opcode :: Sshr => Cost :: new ( 3 , 0 ) ,
88+ | Opcode :: Sshr => Cost :: new ( 3 ) ,
13389
13490 // "Expensive" arithmetic.
135- Opcode :: Imul => Cost :: new ( 10 , 0 ) ,
91+ Opcode :: Imul => Cost :: new ( 10 ) ,
13692
13793 // Everything else.
13894 _ => {
13995 // By default, be slightly more expensive than "simple"
14096 // arithmetic.
141- let mut c = Cost :: new ( 4 , 0 ) ;
97+ let mut c = Cost :: new ( 4 ) ;
14298
14399 // And then get more expensive as the opcode does more side
144100 // effects.
145101 if op. can_trap ( ) || op. other_side_effects ( ) {
146- c = c + Cost :: new ( 10 , 0 ) ;
102+ c = c + Cost :: new ( 10 ) ;
147103 }
148104 if op. can_load ( ) {
149- c = c + Cost :: new ( 20 , 0 ) ;
105+ c = c + Cost :: new ( 20 ) ;
150106 }
151107 if op. can_store ( ) {
152- c = c + Cost :: new ( 50 , 0 ) ;
108+ c = c + Cost :: new ( 50 ) ;
153109 }
154110
155111 c
@@ -163,12 +119,12 @@ impl Cost {
163119 /// that satisfies `inst_predicates::is_pure_for_egraph()`.
164120 pub ( crate ) fn of_pure_op ( op : Opcode , operand_costs : impl IntoIterator < Item = Self > ) -> Self {
165121 let c = Self :: of_opcode ( op) + operand_costs. into_iter ( ) . sum ( ) ;
166- Cost :: new ( c. op_cost ( ) , c . depth ( ) . saturating_add ( 1 ) )
122+ Cost :: new ( c. cost ( ) )
167123 }
168124
169125 /// Compute the cost of an operation in the side-effectful skeleton.
170126 pub ( crate ) fn of_skeleton_op ( op : Opcode , arity : usize ) -> Self {
171- Cost :: of_opcode ( op) + Cost :: new ( u32:: try_from ( arity) . unwrap ( ) , ( arity != 0 ) as _ )
127+ Cost :: of_opcode ( op) + Cost :: new ( u32:: try_from ( arity) . unwrap ( ) )
172128 }
173129}
174130
@@ -188,9 +144,7 @@ impl core::ops::Add<Cost> for Cost {
188144 type Output = Cost ;
189145
190146 fn add ( self , other : Cost ) -> Cost {
191- let op_cost = self . op_cost ( ) . saturating_add ( other. op_cost ( ) ) ;
192- let depth = core:: cmp:: max ( self . depth ( ) , other. depth ( ) ) ;
193- Cost :: new ( op_cost, depth)
147+ Cost :: new ( self . cost ( ) . saturating_add ( other. cost ( ) ) )
194148 }
195149}
196150
@@ -200,39 +154,25 @@ mod tests {
200154
201155 #[ test]
202156 fn add_cost ( ) {
203- let a = Cost :: new ( 5 , 2 ) ;
204- let b = Cost :: new ( 37 , 3 ) ;
205- assert_eq ! ( a + b, Cost :: new( 42 , 3 ) ) ;
206- assert_eq ! ( b + a, Cost :: new( 42 , 3 ) ) ;
157+ let a = Cost :: new ( 5 ) ;
158+ let b = Cost :: new ( 37 ) ;
159+ assert_eq ! ( a + b, Cost :: new( 42 ) ) ;
160+ assert_eq ! ( b + a, Cost :: new( 42 ) ) ;
207161 }
208162
209163 #[ test]
210164 fn add_infinity ( ) {
211- let a = Cost :: new ( 5 , 2 ) ;
165+ let a = Cost :: new ( 5 ) ;
212166 let b = Cost :: infinity ( ) ;
213167 assert_eq ! ( a + b, Cost :: infinity( ) ) ;
214168 assert_eq ! ( b + a, Cost :: infinity( ) ) ;
215169 }
216170
217171 #[ test]
218172 fn op_cost_saturates_to_infinity ( ) {
219- let a = Cost :: new ( Cost :: MAX_OP_COST - 10 , 2 ) ;
220- let b = Cost :: new ( 11 , 2 ) ;
173+ let a = Cost :: new ( u32 :: MAX - 10 ) ;
174+ let b = Cost :: new ( 11 ) ;
221175 assert_eq ! ( a + b, Cost :: infinity( ) ) ;
222176 assert_eq ! ( b + a, Cost :: infinity( ) ) ;
223177 }
224-
225- #[ test]
226- fn depth_saturates_to_max_depth ( ) {
227- let a = Cost :: new ( 10 , u8:: MAX ) ;
228- let b = Cost :: new ( 10 , 1 ) ;
229- assert_eq ! (
230- Cost :: of_pure_op( Opcode :: Iconst , [ a, b] ) ,
231- Cost :: new( 21 , u8 :: MAX )
232- ) ;
233- assert_eq ! (
234- Cost :: of_pure_op( Opcode :: Iconst , [ b, a] ) ,
235- Cost :: new( 21 , u8 :: MAX )
236- ) ;
237- }
238178}
0 commit comments