source: src/ResolvExpr/Cost.h @ 686f731

ADTarm-ehast-experimentalcleanup-dtorsenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since 686f731 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.