source: src/ResolvExpr/Cost.h @ c75b30a

Last change on this file since c75b30a was 2908f08, checked in by Andrew Beach <ajbeach@…>, 8 months ago

Most of ResolvExpr? was written before the new style standard. Some files updated, focus on headers.

  • Property mode set to 100644
File size: 5.9 KB
RevLine 
[a32b204]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//
[b46e3bd]7// Cost.h --
[a32b204]8//
[c378e5e]9// Author           : Peter Buhr and Aaron Moss
[a32b204]10// Created On       : Sun May 17 09:39:50 2015
[cdcddfe1]11// Last Modified By : Peter A. Buhr
[9504a89]12// Last Modified On : Fri Jun 21 11:39:13 2019
13// Update Count     : 63
[a32b204]14//
15
[6b0b624]16#pragma once
[51b7345]17
18#include <iostream>
[c378e5e]19#include <cassert>
[b10c39a0]20#include <climits>
[51b7345]21
22namespace ResolvExpr {
[c378e5e]23
[2908f08]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
78                };
79        }
[c378e5e]80
[2908f08]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; }
88
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 );
[c378e5e]98
[2908f08]99        friend Cost operator+( const Cost lhs, const Cost rhs );
[c378e5e]100
[2908f08]101        Cost operator+=( const Cost rhs ) {
102                if ( all == infinity ) return *this;
103                if ( rhs.all == infinity ) {
104                        all = infinity;
[c378e5e]105                        return *this;
106                }
[2908f08]107                all += rhs.all - correctw;                                      // correct for negative spec cost
108                return *this;
109        }
[c378e5e]110
[2908f08]111        Cost incUnsafe( int inc = 1 ) {
112                if ( all != infinity ) { assert( v.unsafeCost + inc <= UCHAR_MAX ); v.unsafeCost += inc; }
113                return *this;
114        }
[c378e5e]115
[2908f08]116        Cost incPoly( int inc = 1 ) {
117                if ( all != infinity ) { assert( v.polyCost + inc <= UCHAR_MAX ); v.polyCost += inc; }
118                return *this;
119        }
[c378e5e]120
[2908f08]121        Cost incSafe( int inc = 1 ) {
122                if ( all != infinity ) { assert( v.safeCost + inc <= UCHAR_MAX ); v.safeCost += inc; }
123                return *this;
[c378e5e]124        }
125
[2908f08]126        Cost incSign( int inc = 1 ) {
127                if ( all != infinity ) { assert( v.signCost + inc <= UCHAR_MAX ); v.signCost += inc; }
128                return *this;
[c378e5e]129        }
130
[2908f08]131        Cost incVar( int inc = 1 ) {
132                if ( all != infinity ) { assert( v.varCost + inc <= UCHAR_MAX ); v.varCost += inc; }
133                return *this;
[c378e5e]134        }
135
[2908f08]136        Cost decSpec( int dec = 1 ) {
137                if ( all != infinity ) { assert( v.specCost - dec >= 0 ); v.specCost -= dec; }
138                return *this;
[c378e5e]139        }
140
[2908f08]141        Cost incReference( int inc = 1 ) {
142                if ( all != infinity ) { assert( v.referenceCost + inc <= UCHAR_MAX ); v.referenceCost += inc; }
143                return *this;
[c378e5e]144        }
[2908f08]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
[51b7345]174} // namespace ResolvExpr
175
[a32b204]176// Local Variables: //
177// tab-width: 4 //
178// mode: c++ //
179// compile-command: "make install" //
180// End: //
Note: See TracBrowser for help on using the repository browser.