Ignore:
Timestamp:
May 24, 2019, 10:19:41 AM (6 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, cleanup-dtors, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
d908563
Parents:
6a9d4b4 (diff), 292642a (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' into cleanup-dtors

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Cost.h

    r6a9d4b4 r933f32f  
    77// Cost.h --
    88//
    9 // Author           : Richard C. Bilson
     9// Author           : Peter Buhr and Aaron Moss
    1010// Created On       : Sun May 17 09:39:50 2015
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Fri Oct 05 14:32:00 2018
    13 // Update Count     : 7
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Mon Apr 29 18:33:44 2019
     13// Update Count     : 49
    1414//
    1515
     
    1717
    1818#include <iostream>
     19#include <cassert>
     20#include <climits>
    1921
    2022namespace ResolvExpr {
     23#if 0
     24
     25        //*************************** OLD ***************************
     26
    2127        class Cost {
    2228          private:
    23                 Cost( int unsafeCost, int polyCost, int safeCost, int varCost, int specCost,
    24                         int referenceCost );
    25 
     29                Cost( int unsafeCost, int polyCost, int safeCost, int signCost,
     30                          int varCost, int specCost, int referenceCost );
    2631          public:
    2732                Cost & incUnsafe( int inc = 1 );
    2833                Cost & incPoly( int inc = 1 );
    2934                Cost & incSafe( int inc = 1 );
     35                Cost & incSign( int inc = 1 );
    3036                Cost & incVar( int inc = 1 );
    3137                Cost & decSpec( int inc = 1 );
     
    3541                int get_polyCost() const { return polyCost; }
    3642                int get_safeCost() const { return safeCost; }
     43                int get_signCost() const { return signCost; }
    3744                int get_varCost() const { return varCost; }
    3845                int get_specCost() const { return specCost; }
     
    4047
    4148                Cost operator+( const Cost &other ) const;
    42                 Cost operator-( const Cost &other ) const;
    4349                Cost &operator+=( const Cost &other );
    4450                bool operator<( const Cost &other ) const;
     
    5561                static const Cost poly;
    5662                static const Cost safe;
     63                static const Cost sign;
    5764                static const Cost var;
    5865                static const Cost spec;
     
    6370                int polyCost;       ///< Count of parameters and return values bound to some poly type
    6471                int safeCost;       ///< Safe (widening) conversions
     72                int signCost;       ///< Count of safe sign conversions
    6573                int varCost;        ///< Count of polymorphic type variables
    6674                int specCost;       ///< Polymorphic type specializations (type assertions), negative cost
     
    6876        };
    6977
    70         inline Cost::Cost( int unsafeCost, int polyCost, int safeCost, int varCost, int specCost,
    71                         int referenceCost )
    72                 : unsafeCost( unsafeCost ), polyCost( polyCost ), safeCost( safeCost ), varCost( varCost ),
    73                   specCost( specCost ), referenceCost( referenceCost ) {}
     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 ) {}
    7482
    7583        inline Cost & Cost::incUnsafe( int inc ) {
     
    8896                if ( *this == infinity ) return *this;
    8997                safeCost += inc;
     98                return *this;
     99        }
     100
     101        inline Cost & Cost::incSign( int inc ) {
     102                if ( *this == infinity ) return *this;
     103                signCost += inc;
    90104                return *this;
    91105        }
     
    111125        inline Cost Cost::operator+( const Cost &other ) const {
    112126                if ( *this == infinity || other == infinity ) return infinity;
    113                 return Cost{
    114                         unsafeCost + other.unsafeCost, polyCost + other.polyCost, safeCost + other.safeCost,
    115                         varCost + other.varCost, specCost + other.specCost,
    116                         referenceCost + other.referenceCost };
    117         }
    118 
    119         inline Cost Cost::operator-( const Cost &other ) const {
    120                 if ( *this == infinity || other == infinity ) return infinity;
    121                 return Cost{
    122                         unsafeCost - other.unsafeCost, polyCost - other.polyCost, safeCost - other.safeCost,
    123                         varCost - other.varCost, specCost - other.specCost,
    124                         referenceCost - other.referenceCost };
     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 };
    125131        }
    126132
     
    134140                polyCost += other.polyCost;
    135141                safeCost += other.safeCost;
     142                signCost += other.signCost;
    136143                varCost += other.varCost;
    137144                specCost += other.specCost;
     
    156163                } else if ( safeCost < other.safeCost ) {
    157164                        return true;
     165                } else if ( signCost > other.signCost ) {
     166                        return false;
     167                } else if ( signCost < other.signCost ) {
     168                        return true;
    158169                } else if ( varCost > other.varCost ) {
    159170                        return false;
     
    180191                c = polyCost - other.polyCost; if ( c ) return c;
    181192                c = safeCost - other.safeCost; if ( c ) return c;
     193                c = signCost - other.signCost; if ( c ) return c;
    182194                c = varCost - other.varCost; if ( c ) return c;
    183195                c = specCost - other.specCost; if ( c ) return c;
     
    189201                        && polyCost == other.polyCost
    190202                        && safeCost == other.safeCost
     203                        && signCost == other.signCost
    191204                        && varCost == other.varCost
    192205                        && specCost == other.specCost
     
    199212
    200213        inline std::ostream &operator<<( std::ostream &os, const Cost &cost ) {
    201                 return os << "( " << cost.unsafeCost << ", " << cost.polyCost << ", "
    202                           << cost.safeCost << ", " << cost.varCost << ", " << cost.specCost << ", "
     214                return os << "( " << cost.unsafeCost << ", " << cost.polyCost << ", "
     215                          << cost.safeCost << ", " << cost.signCost << ", "
     216                                  << cost.varCost << ", " << cost.specCost << ", "
    203217                          << cost.referenceCost << " )";
    204218        }
     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
    205374} // namespace ResolvExpr
    206375
Note: See TracChangeset for help on using the changeset viewer.