Ignore:
Timestamp:
Oct 29, 2019, 4:01:24 PM (6 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
773db65, 9421f3d8
Parents:
7951100 (diff), 8364209 (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

    r7951100 rb067d9b  
    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
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:35:55 2017
    13 // Update Count     : 5
     12// Last Modified On : Fri Jun 21 11:39:13 2019
     13// Update Count     : 63
    1414//
    1515
     
    1717
    1818#include <iostream>
     19#include <cassert>
     20#include <climits>
    1921
    2022namespace 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.
     25
    2126        class Cost {
    22           private:
    23                 Cost( int unsafeCost, int polyCost, int safeCost, int referenceCost );
     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;
     44                };
     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                }; //'
    2460
    25           public:
    26                 Cost & incUnsafe( int inc = 1 );
    27                 Cost & incPoly( int inc = 1 );
    28                 Cost & incSafe( int inc = 1 );
    29                 Cost & incReference( int inc = 1 );
     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                }
    3079
    31                 int get_unsafeCost() const { return unsafeCost; }
    32                 int get_polyCost() const { return polyCost; }
    33                 int get_safeCost() const { return safeCost; }
    34                 int get_referenceCost() const { return referenceCost; }
     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; }
    3587
    36                 Cost operator+( const Cost &other ) const;
    37                 Cost operator-( const Cost &other ) const;
    38                 Cost &operator+=( const Cost &other );
    39                 bool operator<( const Cost &other ) const;
    40                 bool operator==( const Cost &other ) const;
    41                 bool operator!=( const Cost &other ) const;
    42                 friend std::ostream &operator<<( std::ostream &os, const Cost &cost );
     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 );
    4397
    44                 static const Cost zero;
    45                 static const Cost infinity;
     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
     107                        return *this;
     108                }
    46109
    47                 static const Cost unsafe;
    48                 static const Cost poly;
    49                 static const Cost safe;
    50                 static const Cost reference;
    51           private:
    52                 int compare( const Cost &other ) const;
     110                Cost incUnsafe( int inc = 1 ) {
     111                        if ( all != infinity ) { assert( v.unsafeCost + inc <= UCHAR_MAX ); v.unsafeCost += inc; }
     112                        return *this;
     113                }
    53114
    54                 int unsafeCost;
    55                 int polyCost;
    56                 int safeCost;
    57                 int referenceCost;
     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 );
    58146        };
    59147
    60         inline Cost::Cost( int unsafeCost, int polyCost, int safeCost, int referenceCost ) : unsafeCost( unsafeCost ), polyCost( polyCost ), safeCost( safeCost ), referenceCost( referenceCost ) {}
    61 
    62         inline Cost & Cost::incUnsafe( int inc ) {
    63                 if ( *this == infinity ) return *this;
    64                 unsafeCost += inc;
    65                 return *this;
     148        inline bool operator==( const Cost lhs, const Cost rhs ) {
     149                return lhs.all == rhs.all;
    66150        }
    67151
    68         inline Cost & Cost::incPoly( int inc ) {
    69                 if ( *this == infinity ) return *this;
    70                 polyCost += inc;
    71                 return *this;
     152        inline bool operator!=( const Cost lhs, const Cost rhs ) {
     153                return !( lhs.all == rhs.all );
    72154        }
    73155
    74         inline Cost & Cost::incSafe( int inc ) {
    75                 if ( *this == infinity ) return *this;
    76                 safeCost += inc;
    77                 return *this;
     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;
    78160        }
    79161
    80         inline Cost & Cost::incReference( int inc ) {
    81                 if ( *this == infinity ) return *this;
    82                 referenceCost += inc;
    83                 return *this;
     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
    84165        }
    85166
    86         inline Cost Cost::operator+( const Cost &other ) const {
    87                 if ( *this == infinity || other == infinity ) return infinity;
    88                 return Cost( unsafeCost + other.unsafeCost, polyCost + other.polyCost, safeCost + other.safeCost, referenceCost + other.referenceCost );
    89         }
    90 
    91         inline Cost Cost::operator-( const Cost &other ) const {
    92                 if ( *this == infinity || other == infinity ) return infinity;
    93                 return Cost( unsafeCost - other.unsafeCost, polyCost - other.polyCost, safeCost - other.safeCost, referenceCost - other.referenceCost );
    94         }
    95 
    96         inline Cost &Cost::operator+=( const Cost &other ) {
    97                 if ( *this == infinity ) return *this;
    98                 if ( other == infinity ) {
    99                         *this = infinity;
    100                         return *this;
    101                 }
    102                 unsafeCost += other.unsafeCost;
    103                 polyCost += other.polyCost;
    104                 safeCost += other.safeCost;
    105                 referenceCost += other.referenceCost;
    106                 return *this;
    107         }
    108 
    109         inline bool Cost::operator<( const Cost &other ) const {
    110                 if ( *this == infinity ) return false;
    111                 if ( other == infinity ) return true;
    112 
    113                 if ( unsafeCost > other.unsafeCost ) {
    114                         return false;
    115                 } else if ( unsafeCost < other.unsafeCost ) {
    116                         return true;
    117                 } else if ( polyCost > other.polyCost ) {
    118                         return false;
    119                 } else if ( polyCost < other.polyCost ) {
    120                         return true;
    121                 } else if ( safeCost > other.safeCost ) {
    122                         return false;
    123                 } else if ( safeCost < other.safeCost ) {
    124                         return true;
    125                 } else if ( referenceCost > other.referenceCost ) {
    126                         return false;
    127                 } else if ( referenceCost < other.referenceCost ) {
    128                         return true;
    129                 } else {
    130                         return false;
    131                 } // if
    132         }
    133 
    134         inline bool Cost::operator==( const Cost &other ) const {
    135                 return unsafeCost == other.unsafeCost
    136                         && polyCost == other.polyCost
    137                         && safeCost == other.safeCost
    138                         && referenceCost == other.referenceCost;
    139         }
    140 
    141         inline bool Cost::operator!=( const Cost &other ) const {
    142                 return !( *this == other );
    143         }
    144 
    145         inline std::ostream &operator<<( std::ostream &os, const Cost &cost ) {
    146                 os << "( " << cost.unsafeCost << ", " << cost.polyCost << ", " << cost.safeCost << ", " << cost.referenceCost << " )";
    147                 return os;
     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() << " )";
    148171        }
    149172} // namespace ResolvExpr
Note: See TracChangeset for help on using the changeset viewer.