Changeset f7f997a for src/ResolvExpr/Cost.h
- Timestamp:
- Nov 17, 2023, 3:23:48 PM (2 years ago)
- Branches:
- master
- Children:
- decd4a6
- Parents:
- 16e0dcb (diff), 2908f08 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - File:
-
- 1 edited
-
src/ResolvExpr/Cost.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/Cost.h
r16e0dcb rf7f997a 21 21 22 22 namespace ResolvExpr { 23 // To maximize performance and space, the 7 resolution costs are packed into a single 64-bit word. However, the24 // specialization cost is a negative value so a correction is needed is a few places.25 23 26 class Cost { 27 union { 28 struct { 29 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 30 // Little-endian => first value is low priority and last is high priority. 31 unsigned char padding; ///< unused 32 unsigned char referenceCost; ///< reference conversions 33 unsigned char specCost; ///< Polymorphic type specializations (type assertions), negative cost 34 unsigned char varCost; ///< Count of polymorphic type variables 35 unsigned char signCost; ///< Count of safe sign conversions 36 unsigned char safeCost; ///< Safe (widening) conversions 37 unsigned char polyCost; ///< Count of parameters and return values bound to some poly type 38 unsigned char unsafeCost; ///< Unsafe (narrowing) conversions 39 #else 40 #error Cost BIG_ENDIAN unsupported 41 #endif 42 } v; 43 uint64_t all; 24 // To maximize performance and space, the 7 resolution costs are packed into a single 64-bit word. However, the 25 // specialization cost is a negative value so a correction is needed is a few places. 26 27 class Cost { 28 union { 29 struct { 30 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 31 // Little-endian => first value is low priority and last is high priority. 32 unsigned char padding; ///< unused 33 unsigned char referenceCost; ///< reference conversions 34 unsigned char specCost; ///< Polymorphic type specializations (type assertions), negative cost 35 unsigned char varCost; ///< Count of polymorphic type variables 36 unsigned char signCost; ///< Count of safe sign conversions 37 unsigned char safeCost; ///< Safe (widening) conversions 38 unsigned char polyCost; ///< Count of parameters and return values bound to some poly type 39 unsigned char unsafeCost; ///< Unsafe (narrowing) conversions 40 #else 41 #error Cost BIG_ENDIAN unsupported 42 #endif 43 } v; 44 uint64_t all; 45 }; 46 static const unsigned char correctb = 0xff; // byte correction for negative spec cost 47 static const uint64_t correctw = 0x00'00'00'00'00'ff'00'00; //' word correction for negative spec cost 48 public: 49 // Compiler adjusts constants for correct endian. 50 enum : uint64_t { 51 zero = 0x00'00'00'00'00'ff'00'00, 52 infinity = 0xff'ff'ff'ff'ff'00'ff'ff, 53 unsafe = 0x01'00'00'00'00'ff'00'00, 54 poly = 0x00'01'00'00'00'ff'00'00, 55 safe = 0x00'00'01'00'00'ff'00'00, 56 sign = 0x00'00'00'01'00'ff'00'00, 57 var = 0x00'00'00'00'01'ff'00'00, 58 spec = 0x00'00'00'00'00'fe'00'00, 59 reference = 0x00'00'00'00'00'ff'01'00, 60 }; //' 61 62 Cost( uint64_t all ) { Cost::all = all; } 63 Cost( int unsafeCost, int polyCost, int safeCost, int signCost, int varCost, int specCost, int referenceCost ) { 64 // Assume little-endian => first value is low priority and last is high priority. 65 v = { 66 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 67 (unsigned char)0, // padding 68 (unsigned char)referenceCost, // low priority 69 (unsigned char)(specCost + correctb), // correct for signedness 70 (unsigned char)varCost, 71 (unsigned char)signCost, 72 (unsigned char)safeCost, 73 (unsigned char)polyCost, 74 (unsigned char)unsafeCost, // high priority 75 #else 76 #error Cost BIG_ENDIAN unsupported 77 #endif 44 78 }; 45 static const unsigned char correctb = 0xff; // byte correction for negative spec cost 46 static const uint64_t correctw = 0x00'00'00'00'00'ff'00'00; //' word correction for negative spec cost 47 public: 48 // Compiler adjusts constants for correct endian. 49 enum : uint64_t { 50 zero = 0x00'00'00'00'00'ff'00'00, 51 infinity = 0xff'ff'ff'ff'ff'00'ff'ff, 52 unsafe = 0x01'00'00'00'00'ff'00'00, 53 poly = 0x00'01'00'00'00'ff'00'00, 54 safe = 0x00'00'01'00'00'ff'00'00, 55 sign = 0x00'00'00'01'00'ff'00'00, 56 var = 0x00'00'00'00'01'ff'00'00, 57 spec = 0x00'00'00'00'00'fe'00'00, 58 reference = 0x00'00'00'00'00'ff'01'00, 59 }; //' 79 } 60 80 61 Cost( uint64_t all ) { Cost::all = all; } 62 Cost( int unsafeCost, int polyCost, int safeCost, int signCost, int varCost, int specCost, int referenceCost ) { 63 // Assume little-endian => first value is low priority and last is high priority. 64 v = { 65 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 66 (unsigned char)0, // padding 67 (unsigned char)referenceCost, // low priority 68 (unsigned char)(specCost + correctb), // correct for signedness 69 (unsigned char)varCost, 70 (unsigned char)signCost, 71 (unsigned char)safeCost, 72 (unsigned char)polyCost, 73 (unsigned char)unsafeCost, // high priority 74 #else 75 #error Cost BIG_ENDIAN unsupported 76 #endif 77 }; 78 } 81 int get_unsafeCost() const { return v.unsafeCost; } 82 int get_polyCost() const { return v.polyCost; } 83 int get_safeCost() const { return v.safeCost; } 84 int get_signCost() const { return v.signCost; } 85 int get_varCost() const { return v.varCost; } 86 int get_specCost() const { return -(correctb - v.specCost); } 87 int get_referenceCost() const { return v.referenceCost; } 79 88 80 int get_unsafeCost() const { return v.unsafeCost; } 81 int get_polyCost() const { return v.polyCost; } 82 int get_safeCost() const { return v.safeCost; } 83 int get_signCost() const { return v.signCost; } 84 int get_varCost() const { return v.varCost; } 85 int get_specCost() const { return -(correctb - v.specCost); } 86 int get_referenceCost() const { return v.referenceCost; } 89 friend bool operator==( const Cost, const Cost ); 90 friend bool operator!=( const Cost lhs, const Cost rhs ); 91 // returns negative for *this < rhs, 0 for *this == rhs, positive for *this > rhs 92 int compare( const Cost rhs ) const { 93 if ( all == infinity ) return 1; 94 if ( rhs.all == infinity ) return -1; 95 return all > rhs.all ? 1 : all == rhs.all ? 0 : -1; 96 } 97 friend bool operator<( const Cost lhs, const Cost rhs ); 87 98 88 friend bool operator==( const Cost, const Cost ); 89 friend bool operator!=( const Cost lhs, const Cost rhs ); 90 // returns negative for *this < rhs, 0 for *this == rhs, positive for *this > rhs 91 int compare( const Cost rhs ) const { 92 if ( all == infinity ) return 1; 93 if ( rhs.all == infinity ) return -1; 94 return all > rhs.all ? 1 : all == rhs.all ? 0 : -1; 95 } 96 friend bool operator<( const Cost lhs, const Cost rhs ); 99 friend Cost operator+( const Cost lhs, const Cost rhs ); 97 100 98 friend Cost operator+( const Cost lhs, const Cost rhs ); 99 100 Cost operator+=( const Cost rhs ) { 101 if ( all == infinity ) return *this; 102 if ( rhs.all == infinity ) { 103 all = infinity; 104 return *this; 105 } 106 all += rhs.all - correctw; // correct for negative spec cost 101 Cost operator+=( const Cost rhs ) { 102 if ( all == infinity ) return *this; 103 if ( rhs.all == infinity ) { 104 all = infinity; 107 105 return *this; 108 106 } 109 110 Cost incUnsafe( int inc = 1 ) { 111 if ( all != infinity ) { assert( v.unsafeCost + inc <= UCHAR_MAX ); v.unsafeCost += inc; } 112 return *this; 113 } 114 115 Cost incPoly( int inc = 1 ) { 116 if ( all != infinity ) { assert( v.polyCost + inc <= UCHAR_MAX ); v.polyCost += inc; } 117 return *this; 118 } 119 120 Cost incSafe( int inc = 1 ) { 121 if ( all != infinity ) { assert( v.safeCost + inc <= UCHAR_MAX ); v.safeCost += inc; } 122 return *this; 123 } 124 125 Cost incSign( int inc = 1 ) { 126 if ( all != infinity ) { assert( v.signCost + inc <= UCHAR_MAX ); v.signCost += inc; } 127 return *this; 128 } 129 130 Cost incVar( int inc = 1 ) { 131 if ( all != infinity ) { assert( v.varCost + inc <= UCHAR_MAX ); v.varCost += inc; } 132 return *this; 133 } 134 135 Cost decSpec( int dec = 1 ) { 136 if ( all != infinity ) { assert( v.specCost - dec >= 0 ); v.specCost -= dec; } 137 return *this; 138 } 139 140 Cost incReference( int inc = 1 ) { 141 if ( all != infinity ) { assert( v.referenceCost + inc <= UCHAR_MAX ); v.referenceCost += inc; } 142 return *this; 143 } 144 145 friend std::ostream & operator<<( std::ostream & os, const Cost cost ); 146 }; 147 148 inline bool operator==( const Cost lhs, const Cost rhs ) { 149 return lhs.all == rhs.all; 107 all += rhs.all - correctw; // correct for negative spec cost 108 return *this; 150 109 } 151 110 152 inline bool operator!=( const Cost lhs, const Cost rhs ) { 153 return !( lhs.all == rhs.all ); 111 Cost incUnsafe( int inc = 1 ) { 112 if ( all != infinity ) { assert( v.unsafeCost + inc <= UCHAR_MAX ); v.unsafeCost += inc; } 113 return *this; 154 114 } 155 115 156 inline bool operator<( const Cost lhs, const Cost rhs ) { 157 if ( lhs.all == Cost::infinity ) return false; 158 if ( rhs.all == Cost::infinity ) return true; 159 return lhs.all < rhs.all; 116 Cost incPoly( int inc = 1 ) { 117 if ( all != infinity ) { assert( v.polyCost + inc <= UCHAR_MAX ); v.polyCost += inc; } 118 return *this; 160 119 } 161 120 162 inline Cost operator+( const Cost lhs, const Cost rhs) {163 if ( lhs.all == Cost::infinity || rhs.all == Cost::infinity ) return Cost{ Cost::infinity };164 return Cost{ lhs.all + rhs.all - Cost::correctw }; // correct for negative spec cost121 Cost incSafe( int inc = 1 ) { 122 if ( all != infinity ) { assert( v.safeCost + inc <= UCHAR_MAX ); v.safeCost += inc; } 123 return *this; 165 124 } 166 125 167 inline std::ostream & operator<<( std::ostream & os, const Cost cost ) { 168 return os << "( " << cost.get_unsafeCost() << ", " << cost.get_polyCost() << ", " << cost.get_safeCost() 169 << ", " << cost.get_signCost() << ", " << cost.get_varCost() << ", " << cost.get_specCost() 170 << ", " << cost.get_referenceCost() << " )"; 126 Cost incSign( int inc = 1 ) { 127 if ( all != infinity ) { assert( v.signCost + inc <= UCHAR_MAX ); v.signCost += inc; } 128 return *this; 171 129 } 130 131 Cost incVar( int inc = 1 ) { 132 if ( all != infinity ) { assert( v.varCost + inc <= UCHAR_MAX ); v.varCost += inc; } 133 return *this; 134 } 135 136 Cost decSpec( int dec = 1 ) { 137 if ( all != infinity ) { assert( v.specCost - dec >= 0 ); v.specCost -= dec; } 138 return *this; 139 } 140 141 Cost incReference( int inc = 1 ) { 142 if ( all != infinity ) { assert( v.referenceCost + inc <= UCHAR_MAX ); v.referenceCost += inc; } 143 return *this; 144 } 145 146 friend std::ostream & operator<<( std::ostream & os, const Cost cost ); 147 }; 148 149 inline bool operator==( const Cost lhs, const Cost rhs ) { 150 return lhs.all == rhs.all; 151 } 152 153 inline bool operator!=( const Cost lhs, const Cost rhs ) { 154 return !( lhs.all == rhs.all ); 155 } 156 157 inline bool operator<( const Cost lhs, const Cost rhs ) { 158 if ( lhs.all == Cost::infinity ) return false; 159 if ( rhs.all == Cost::infinity ) return true; 160 return lhs.all < rhs.all; 161 } 162 163 inline Cost operator+( const Cost lhs, const Cost rhs ) { 164 if ( lhs.all == Cost::infinity || rhs.all == Cost::infinity ) return Cost{ Cost::infinity }; 165 return Cost{ lhs.all + rhs.all - Cost::correctw }; // correct for negative spec cost 166 } 167 168 inline std::ostream & operator<<( std::ostream & os, const Cost cost ) { 169 return os << "( " << cost.get_unsafeCost() << ", " << cost.get_polyCost() << ", " << cost.get_safeCost() 170 << ", " << cost.get_signCost() << ", " << cost.get_varCost() << ", " << cost.get_specCost() 171 << ", " << cost.get_referenceCost() << " )"; 172 } 173 172 174 } // namespace ResolvExpr 173 175
Note:
See TracChangeset
for help on using the changeset viewer.