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
RevLine 
[a32b204]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//
[b46e3bd]7// Cost.h --
[a32b204]8//
[c378e5e]9// Author : Peter Buhr and Aaron Moss
[a32b204]10// Created On : Sun May 17 09:39:50 2015
[cdcddfe1]11// Last Modified By : Peter A. Buhr
[c378e5e]12// Last Modified On : Sun Apr 28 18:26:36 2019
13// Update Count : 29
[a32b204]14//
15
[6b0b624]16#pragma once
[51b73452]17
18#include <iostream>
[c378e5e]19#include <cassert>
[51b73452]20
21namespace ResolvExpr {
[c378e5e]22#if 0
23
24 //*************************** OLD ***************************
25
[a32b204]26 class Cost {
[89be1c68]27 private:
[cdcddfe1]28 Cost( int unsafeCost, int polyCost, int safeCost, int signCost,
[c378e5e]29 int varCost, int specCost, int referenceCost );
[89be1c68]30 public:
31 Cost & incUnsafe( int inc = 1 );
32 Cost & incPoly( int inc = 1 );
[d97c3a4]33 Cost & incSafe( int inc = 1 );
[cdcddfe1]34 Cost & incSign( int inc = 1 );
[1dd1bd2]35 Cost & incVar( int inc = 1 );
36 Cost & decSpec( int inc = 1 );
[7ebaa56]37 Cost & incReference( int inc = 1 );
[b46e3bd]38
[ddf8a29]39 int get_unsafeCost() const { return unsafeCost; }
40 int get_polyCost() const { return polyCost; }
[d97c3a4]41 int get_safeCost() const { return safeCost; }
[cdcddfe1]42 int get_signCost() const { return signCost; }
[1dd1bd2]43 int get_varCost() const { return varCost; }
44 int get_specCost() const { return specCost; }
[ddf8a29]45 int get_referenceCost() const { return referenceCost; }
46
[a32b204]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 );
[6d6e829]53 // returns negative for *this < other, 0 for *this == other, positive for *this > other
54 int compare( const Cost &other ) const;
[b46e3bd]55
[a32b204]56 static const Cost zero;
57 static const Cost infinity;
[7ebaa56]58
[b46e3bd]59 static const Cost unsafe;
60 static const Cost poly;
[d97c3a4]61 static const Cost safe;
[cdcddfe1]62 static const Cost sign;
[1dd1bd2]63 static const Cost var;
64 static const Cost spec;
[7ebaa56]65 static const Cost reference;
[a32b204]66
[6d6e829]67 private:
[1dd1bd2]68 int unsafeCost; ///< Unsafe (narrowing) conversions
69 int polyCost; ///< Count of parameters and return values bound to some poly type
[d97c3a4]70 int safeCost; ///< Safe (widening) conversions
[cdcddfe1]71 int signCost; ///< Count of safe sign conversions
[1dd1bd2]72 int varCost; ///< Count of polymorphic type variables
73 int specCost; ///< Polymorphic type specializations (type assertions), negative cost
74 int referenceCost; ///< reference conversions
[a32b204]75 };
76
[cdcddfe1]77 inline Cost::Cost( int unsafeCost, int polyCost, int safeCost, int signCost,
[c378e5e]78 int varCost, int specCost, int referenceCost )
[cdcddfe1]79 : unsafeCost( unsafeCost ), polyCost( polyCost ), safeCost( safeCost ), signCost( signCost ),
80 varCost( varCost ), specCost( specCost ), referenceCost( referenceCost ) {}
[a32b204]81
[89be1c68]82 inline Cost & Cost::incUnsafe( int inc ) {
[17f22e78]83 if ( *this == infinity ) return *this;
[b46e3bd]84 unsafeCost += inc;
[89be1c68]85 return *this;
[a32b204]86 }
87
[89be1c68]88 inline Cost & Cost::incPoly( int inc ) {
[17f22e78]89 if ( *this == infinity ) return *this;
[b46e3bd]90 polyCost += inc;
[89be1c68]91 return *this;
[a32b204]92 }
93
[d97c3a4]94 inline Cost & Cost::incSafe( int inc ) {
[1dd1bd2]95 if ( *this == infinity ) return *this;
[d97c3a4]96 safeCost += inc;
[1dd1bd2]97 return *this;
98 }
99
[cdcddfe1]100 inline Cost & Cost::incSign( int inc ) {
101 if ( *this == infinity ) return *this;
102 signCost += inc;
103 return *this;
104 }
105
[d97c3a4]106 inline Cost & Cost::incVar( int inc ) {
[1dd1bd2]107 if ( *this == infinity ) return *this;
[d97c3a4]108 varCost += inc;
[1dd1bd2]109 return *this;
110 }
111
[d97c3a4]112 inline Cost& Cost::decSpec( int dec ) {
[17f22e78]113 if ( *this == infinity ) return *this;
[d97c3a4]114 specCost -= dec;
[89be1c68]115 return *this;
[a32b204]116 }
117
[7ebaa56]118 inline Cost & Cost::incReference( int inc ) {
[17f22e78]119 if ( *this == infinity ) return *this;
[7ebaa56]120 referenceCost += inc;
121 return *this;
122 }
123
[a32b204]124 inline Cost Cost::operator+( const Cost &other ) const {
[17f22e78]125 if ( *this == infinity || other == infinity ) return infinity;
[cdcddfe1]126 return Cost{
127 unsafeCost + other.unsafeCost, polyCost + other.polyCost, safeCost + other.safeCost,
[c378e5e]128 signCost + other.signCost, varCost + other.varCost, specCost + other.specCost,
129 referenceCost + other.referenceCost };
[a32b204]130 }
131
132 inline Cost &Cost::operator+=( const Cost &other ) {
[17f22e78]133 if ( *this == infinity ) return *this;
134 if ( other == infinity ) {
135 *this = infinity;
136 return *this;
137 }
[b46e3bd]138 unsafeCost += other.unsafeCost;
139 polyCost += other.polyCost;
[d97c3a4]140 safeCost += other.safeCost;
[cdcddfe1]141 signCost += other.signCost;
[1dd1bd2]142 varCost += other.varCost;
143 specCost += other.specCost;
[7ebaa56]144 referenceCost += other.referenceCost;
[a32b204]145 return *this;
146 }
147
148 inline bool Cost::operator<( const Cost &other ) const {
[b46e3bd]149 if ( *this == infinity ) return false;
150 if ( other == infinity ) return true;
151
152 if ( unsafeCost > other.unsafeCost ) {
[a32b204]153 return false;
[b46e3bd]154 } else if ( unsafeCost < other.unsafeCost ) {
[a32b204]155 return true;
[b46e3bd]156 } else if ( polyCost > other.polyCost ) {
[a32b204]157 return false;
[b46e3bd]158 } else if ( polyCost < other.polyCost ) {
[a32b204]159 return true;
[d97c3a4]160 } else if ( safeCost > other.safeCost ) {
161 return false;
162 } else if ( safeCost < other.safeCost ) {
163 return true;
[cdcddfe1]164 } else if ( signCost > other.signCost ) {
165 return false;
166 } else if ( signCost < other.signCost ) {
167 return true;
[1dd1bd2]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;
[7ebaa56]176 } else if ( referenceCost > other.referenceCost ) {
177 return false;
178 } else if ( referenceCost < other.referenceCost ) {
179 return true;
[b46e3bd]180 } else {
[a32b204]181 return false;
[b46e3bd]182 } // if
[d9a0e76]183 }
184
[6d6e829]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;
[d97c3a4]191 c = safeCost - other.safeCost; if ( c ) return c;
[cdcddfe1]192 c = signCost - other.signCost; if ( c ) return c;
[6d6e829]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
[a32b204]198 inline bool Cost::operator==( const Cost &other ) const {
[b46e3bd]199 return unsafeCost == other.unsafeCost
200 && polyCost == other.polyCost
[d97c3a4]201 && safeCost == other.safeCost
[cdcddfe1]202 && signCost == other.signCost
[1dd1bd2]203 && varCost == other.varCost
204 && specCost == other.specCost
[7ebaa56]205 && referenceCost == other.referenceCost;
[a32b204]206 }
[d9a0e76]207
[a32b204]208 inline bool Cost::operator!=( const Cost &other ) const {
209 return !( *this == other );
210 }
[d9a0e76]211
[a32b204]212 inline std::ostream &operator<<( std::ostream &os, const Cost &cost ) {
[cdcddfe1]213 return os << "( " << cost.unsafeCost << ", " << cost.polyCost << ", "
214 << cost.safeCost << ", " << cost.signCost << ", "
215 << cost.varCost << ", " << cost.specCost << ", "
[d97c3a4]216 << cost.referenceCost << " )";
[a32b204]217 }
[c378e5e]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 }
[51b73452]363} // namespace ResolvExpr
364
[a32b204]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.