source: src/ResolvExpr/Cost.h@ b8524ca

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

updates for new Cost class

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