Ignore:
Timestamp:
Nov 17, 2023, 3:23:48 PM (2 years ago)
Author:
caparson <caparson@…>
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.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Cost.h

    r16e0dcb rf7f997a  
    2121
    2222namespace ResolvExpr {
    23         // To maximize performance and space, the 7 resolution costs are packed into a single 64-bit word. However, the
    24         // specialization cost is a negative value so a correction is needed is a few places.
    2523
    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
     27class 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
    4478                };
    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        }
    6080
    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; }
    7988
    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 );
    8798
    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 );
    97100
    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;
    107105                        return *this;
    108106                }
    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;
    150109        }
    151110
    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;
    154114        }
    155115
    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;
    160119        }
    161120
    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 cost
     121        Cost incSafe( int inc = 1 ) {
     122                if ( all != infinity ) { assert( v.safeCost + inc <= UCHAR_MAX ); v.safeCost += inc; }
     123                return *this;
    165124        }
    166125
    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;
    171129        }
     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
     149inline bool operator==( const Cost lhs, const Cost rhs ) {
     150        return lhs.all == rhs.all;
     151}
     152
     153inline bool operator!=( const Cost lhs, const Cost rhs ) {
     154        return !( lhs.all == rhs.all );
     155}
     156
     157inline 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
     163inline 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
     168inline 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
    172174} // namespace ResolvExpr
    173175
Note: See TracChangeset for help on using the changeset viewer.