source: src/ResolvExpr/Cost.h@ 986e260

ADT arm-eh ast-experimental cleanup-dtors enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since 986e260 was c378e5e, checked in by Peter A. Buhr <pabuhr@…>, 7 years ago

pack 7 resolver Costs into single word

  • Property mode set to 100644
File size: 11.6 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// Cost.h --
8//
9// Author : Peter Buhr and Aaron Moss
10// Created On : Sun May 17 09:39:50 2015
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Sun Apr 28 18:26:36 2019
13// Update Count : 29
14//
15
16#pragma once
17
18#include <iostream>
19#include <cassert>
20
21namespace ResolvExpr {
22#if 0
23
24 //*************************** OLD ***************************
25
26 class Cost {
27 private:
28 Cost( int unsafeCost, int polyCost, int safeCost, int signCost,
29 int varCost, int specCost, int referenceCost );
30 public:
31 Cost & incUnsafe( int inc = 1 );
32 Cost & incPoly( int inc = 1 );
33 Cost & incSafe( int inc = 1 );
34 Cost & incSign( int inc = 1 );
35 Cost & incVar( int inc = 1 );
36 Cost & decSpec( int inc = 1 );
37 Cost & incReference( int inc = 1 );
38
39 int get_unsafeCost() const { return unsafeCost; }
40 int get_polyCost() const { return polyCost; }
41 int get_safeCost() const { return safeCost; }
42 int get_signCost() const { return signCost; }
43 int get_varCost() const { return varCost; }
44 int get_specCost() const { return specCost; }
45 int get_referenceCost() const { return referenceCost; }
46
47 Cost operator+( const Cost &other ) const;
48 Cost &operator+=( const Cost &other );
49 bool operator<( const Cost &other ) const;
50 bool operator==( const Cost &other ) const;
51 bool operator!=( const Cost &other ) const;
52 friend std::ostream &operator<<( std::ostream &os, const Cost &cost );
53 // returns negative for *this < other, 0 for *this == other, positive for *this > other
54 int compare( const Cost &other ) const;
55
56 static const Cost zero;
57 static const Cost infinity;
58
59 static const Cost unsafe;
60 static const Cost poly;
61 static const Cost safe;
62 static const Cost sign;
63 static const Cost var;
64 static const Cost spec;
65 static const Cost reference;
66
67 private:
68 int unsafeCost; ///< Unsafe (narrowing) conversions
69 int polyCost; ///< Count of parameters and return values bound to some poly type
70 int safeCost; ///< Safe (widening) conversions
71 int signCost; ///< Count of safe sign conversions
72 int varCost; ///< Count of polymorphic type variables
73 int specCost; ///< Polymorphic type specializations (type assertions), negative cost
74 int referenceCost; ///< reference conversions
75 };
76
77 inline Cost::Cost( int unsafeCost, int polyCost, int safeCost, int signCost,
78 int varCost, int specCost, int referenceCost )
79 : unsafeCost( unsafeCost ), polyCost( polyCost ), safeCost( safeCost ), signCost( signCost ),
80 varCost( varCost ), specCost( specCost ), referenceCost( referenceCost ) {}
81
82 inline Cost & Cost::incUnsafe( int inc ) {
83 if ( *this == infinity ) return *this;
84 unsafeCost += inc;
85 return *this;
86 }
87
88 inline Cost & Cost::incPoly( int inc ) {
89 if ( *this == infinity ) return *this;
90 polyCost += inc;
91 return *this;
92 }
93
94 inline Cost & Cost::incSafe( int inc ) {
95 if ( *this == infinity ) return *this;
96 safeCost += inc;
97 return *this;
98 }
99
100 inline Cost & Cost::incSign( int inc ) {
101 if ( *this == infinity ) return *this;
102 signCost += inc;
103 return *this;
104 }
105
106 inline Cost & Cost::incVar( int inc ) {
107 if ( *this == infinity ) return *this;
108 varCost += inc;
109 return *this;
110 }
111
112 inline Cost& Cost::decSpec( int dec ) {
113 if ( *this == infinity ) return *this;
114 specCost -= dec;
115 return *this;
116 }
117
118 inline Cost & Cost::incReference( int inc ) {
119 if ( *this == infinity ) return *this;
120 referenceCost += inc;
121 return *this;
122 }
123
124 inline Cost Cost::operator+( const Cost &other ) const {
125 if ( *this == infinity || other == infinity ) return infinity;
126 return Cost{
127 unsafeCost + other.unsafeCost, polyCost + other.polyCost, safeCost + other.safeCost,
128 signCost + other.signCost, varCost + other.varCost, specCost + other.specCost,
129 referenceCost + other.referenceCost };
130 }
131
132 inline Cost &Cost::operator+=( const Cost &other ) {
133 if ( *this == infinity ) return *this;
134 if ( other == infinity ) {
135 *this = infinity;
136 return *this;
137 }
138 unsafeCost += other.unsafeCost;
139 polyCost += other.polyCost;
140 safeCost += other.safeCost;
141 signCost += other.signCost;
142 varCost += other.varCost;
143 specCost += other.specCost;
144 referenceCost += other.referenceCost;
145 return *this;
146 }
147
148 inline bool Cost::operator<( const Cost &other ) const {
149 if ( *this == infinity ) return false;
150 if ( other == infinity ) return true;
151
152 if ( unsafeCost > other.unsafeCost ) {
153 return false;
154 } else if ( unsafeCost < other.unsafeCost ) {
155 return true;
156 } else if ( polyCost > other.polyCost ) {
157 return false;
158 } else if ( polyCost < other.polyCost ) {
159 return true;
160 } else if ( safeCost > other.safeCost ) {
161 return false;
162 } else if ( safeCost < other.safeCost ) {
163 return true;
164 } else if ( signCost > other.signCost ) {
165 return false;
166 } else if ( signCost < other.signCost ) {
167 return true;
168 } else if ( varCost > other.varCost ) {
169 return false;
170 } else if ( varCost < other.varCost ) {
171 return true;
172 } else if ( specCost > other.specCost ) {
173 return false;
174 } else if ( specCost > other.specCost ) {
175 return true;
176 } else if ( referenceCost > other.referenceCost ) {
177 return false;
178 } else if ( referenceCost < other.referenceCost ) {
179 return true;
180 } else {
181 return false;
182 } // if
183 }
184
185 inline int Cost::compare( const Cost &other ) const {
186 if ( *this == infinity ) return +1;
187 if ( other == infinity ) return -1;
188
189 int c = unsafeCost - other.unsafeCost; if ( c ) return c;
190 c = polyCost - other.polyCost; if ( c ) return c;
191 c = safeCost - other.safeCost; if ( c ) return c;
192 c = signCost - other.signCost; if ( c ) return c;
193 c = varCost - other.varCost; if ( c ) return c;
194 c = specCost - other.specCost; if ( c ) return c;
195 return referenceCost - other.referenceCost;
196 }
197
198 inline bool Cost::operator==( const Cost &other ) const {
199 return unsafeCost == other.unsafeCost
200 && polyCost == other.polyCost
201 && safeCost == other.safeCost
202 && signCost == other.signCost
203 && varCost == other.varCost
204 && specCost == other.specCost
205 && referenceCost == other.referenceCost;
206 }
207
208 inline bool Cost::operator!=( const Cost &other ) const {
209 return !( *this == other );
210 }
211
212 inline std::ostream &operator<<( std::ostream &os, const Cost &cost ) {
213 return os << "( " << cost.unsafeCost << ", " << cost.polyCost << ", "
214 << cost.safeCost << ", " << cost.signCost << ", "
215 << cost.varCost << ", " << cost.specCost << ", "
216 << cost.referenceCost << " )";
217 }
218#endif // 0
219
220 //*************************** NEW ***************************
221
222 class Cost {
223 union {
224 struct {
225 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
226 // Little-endian => first value is low priority and last is high priority.
227 unsigned char padding; ///< unused
228 unsigned char referenceCost; ///< reference conversions
229 unsigned char specCost; ///< Polymorphic type specializations (type assertions), negative cost
230 unsigned char varCost; ///< Count of polymorphic type variables
231 unsigned char signCost; ///< Count of safe sign conversions
232 unsigned char safeCost; ///< Safe (widening) conversions
233 unsigned char polyCost; ///< Count of parameters and return values bound to some poly type
234 unsigned char unsafeCost; ///< Unsafe (narrowing) conversions
235 #else
236 #error BIG_ENDIAN unsupported
237 #endif
238 } v;
239 uint64_t all;
240 };
241 public:
242 // Compiler adjusts constants for correct endian.
243 enum : uint64_t {
244 zero = 0x00'00'00'00'00'ff'00'00,
245 infinity = 0xff'ff'ff'ff'ff'00'ff'ff,
246 correction = 0x00'00'00'00'00'ff'00'00, // correct for negative spec cost
247 unsafe = 0x01'00'00'00'00'ff'00'00,
248 poly = 0x00'01'00'00'00'ff'00'00,
249 safe = 0x00'00'01'00'00'ff'00'00,
250 sign = 0x00'00'00'01'00'ff'00'00,
251 var = 0x00'00'00'00'01'ff'00'00,
252 spec = 0x00'00'00'00'00'fe'00'00,
253 reference = 0x00'00'00'00'00'ff'01'00,
254 }; //
255
256 Cost( uint64_t all ) { Cost::all = all; }
257 Cost( int unsafeCost, int polyCost, int safeCost, int signCost, int varCost, int specCost, int referenceCost ) {
258 // Assume little-endian => first value is low priority and last is high priority.
259 v = {
260 (unsigned char)0, // padding
261 (unsigned char)referenceCost,
262 (unsigned char)(specCost + 0xff ), // correct for signedness
263 (unsigned char)varCost,
264 (unsigned char)signCost,
265 (unsigned char)safeCost,
266 (unsigned char)polyCost,
267 (unsigned char)unsafeCost,
268 };
269 }
270
271 int get_unsafeCost() const { return v.unsafeCost; }
272 int get_polyCost() const { return v.polyCost; }
273 int get_safeCost() const { return v.safeCost; }
274 int get_signCost() const { return v.signCost; }
275 int get_varCost() const { return v.varCost; }
276 int get_specCost() const { return -(0xff - v.specCost); }
277 int get_referenceCost() const { return v.referenceCost; }
278
279 friend bool operator==( const Cost, const Cost );
280 friend bool operator!=( const Cost lhs, const Cost rhs );
281 // returns negative for *this < rhs, 0 for *this == rhs, positive for *this > rhs
282 int compare( const Cost rhs ) const {
283 if ( all == infinity ) return 1;
284 if ( rhs.all == infinity ) return -1;
285 return all > rhs.all ? 1 : all == rhs.all ? 0 : -1;
286 }
287 friend bool operator<( const Cost lhs, const Cost rhs );
288
289 friend Cost operator+( const Cost lhs, const Cost rhs );
290
291 Cost operator+=( const Cost rhs ) {
292 if ( all == infinity ) return *this;
293 if ( rhs.all == infinity ) {
294 all = infinity;
295 return *this;
296 }
297 all += rhs.all - correction; // correct for negative spec cost
298 return *this;
299 }
300
301 Cost incUnsafe( int inc = 1 ) {
302 if ( all != infinity ) { assert( v.unsafeCost + inc < 256 ); v.unsafeCost += inc; }
303 return *this;
304 }
305
306 Cost incPoly( int inc = 1 ) {
307 if ( all != infinity ) { assert( v.polyCost + inc < 256 ); v.polyCost += inc; }
308 return *this;
309 }
310
311 Cost incSafe( int inc = 1 ) {
312 if ( all != infinity ) { assert( v.safeCost + inc < 256 ); v.safeCost += inc; }
313 return *this;
314 }
315
316 Cost incSign( int inc = 1 ) {
317 if ( all != infinity ) { assert( v.signCost + inc < 256 ); v.signCost += inc; }
318 return *this;
319 }
320
321 Cost incVar( int inc = 1 ) {
322 if ( all != infinity ) { assert( v.varCost + inc < 256 ); v.varCost += inc; }
323 return *this;
324 }
325
326 Cost decSpec( int dec = 1 ) {
327 if ( all != infinity ) { v.specCost -= dec; }
328 return *this;
329 }
330
331 Cost incReference( int inc = 1 ) {
332 if ( all != infinity ) { assert( v.referenceCost + inc < 256 ); v.referenceCost += inc; }
333 return *this;
334 }
335
336 friend std::ostream & operator<<( std::ostream & os, const Cost cost );
337 };
338
339 inline bool operator==( const Cost lhs, const Cost rhs ) {
340 return lhs.all == rhs.all;
341 }
342
343 inline bool operator!=( const Cost lhs, const Cost rhs ) {
344 return !( lhs.all == rhs.all );
345 }
346
347 inline bool operator<( const Cost lhs, const Cost rhs ) {
348 if ( lhs.all == Cost::infinity ) return false;
349 if ( rhs.all == Cost::infinity ) return true;
350 return lhs.all < rhs.all;
351 }
352
353 inline Cost operator+( const Cost lhs, const Cost rhs ) {
354 if ( lhs.all == Cost::infinity || rhs.all == Cost::infinity ) return Cost{ Cost::infinity };
355 return Cost{ lhs.all + rhs.all - Cost::correction }; // correct for negative spec cost
356 }
357
358 inline std::ostream & operator<<( std::ostream & os, const Cost cost ) {
359 return os << "( " << cost.get_unsafeCost() << ", " << cost.get_polyCost() << ", " << cost.get_safeCost()
360 << ", " << cost.get_signCost() << ", " << cost.get_varCost() << ", " << cost.get_specCost()
361 << ", " << cost.get_referenceCost() << " )";
362 }
363} // namespace ResolvExpr
364
365// Local Variables: //
366// tab-width: 4 //
367// mode: c++ //
368// compile-command: "make install" //
369// End: //
Note: See TracBrowser for help on using the repository browser.