source: src/ResolvExpr/Cost.hpp @ 3b10778

Last change on this file since 3b10778 was 06ecda9, checked in by JiadaL <j82liang@…>, 5 days ago

define enum to value cost as implicit cost

  • Property mode set to 100644
File size: 6.3 KB
Line 
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//
7// Cost.h --
8//
9// Author           : Peter Buhr and Aaron Moss
10// Created On       : Sun May 17 09:39:50 2015
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Fri May  3 17:15:41 2024
13// Update Count     : 64
14//
15
16#pragma once
17
18#include <iostream>
19#include <cassert>
20#include <climits>
21#include <cstdint>
22
23namespace ResolvExpr {
24
25// To maximize performance and space, the 7 resolution costs are packed into a single 64-bit word. However, the
26// specialization cost is a negative value so a correction is needed is a few places.
27
28class Cost {
29        union {
30                struct {
31                #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
32                        // Little-endian => first value is low priority and last is high priority.
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 implicitCost;                             ///< Aggregate implicit cost
40                        unsigned char unsafeCost;                               ///< Unsafe (narrowing) conversions
41                #else
42                        #error Cost BIG_ENDIAN unsupported
43                #endif
44                } v;
45                uint64_t all;
46        };
47        static const unsigned char correctb = 0xff;             // byte correction for negative spec cost
48        static const uint64_t correctw = 0x00'00'00'00'00'00'ff'00; //' word correction for negative spec cost
49  public:
50        // Compiler adjusts constants for correct endian.
51        enum : uint64_t {
52                zero      = 0x00'00'00'00'00'00'ff'00,
53                infinity  = 0xff'ff'ff'ff'ff'ff'00'ff,
54                unsafe    = 0x01'00'00'00'00'00'ff'00,
55                implicit  = 0x00'01'00'00'01'00'ff'00,
56                poly      = 0x00'00'01'00'00'00'ff'00,
57                safe      = 0x00'00'00'01'00'00'ff'00,
58                sign      = 0x00'00'00'00'01'00'ff'00,
59                var       = 0x00'00'00'00'00'01'ff'00,
60                spec      = 0x00'00'00'00'00'00'fe'00,
61                reference = 0x00'00'00'00'00'00'ff'01,
62        }; //'
63
64        Cost( uint64_t all ) { Cost::all = all; }
65        Cost( int unsafeCost, int polyCost, int safeCost, int signCost, int implicitCost, int varCost, int specCost, int referenceCost ) {
66                // Assume little-endian => first value is low priority and last is high priority.
67                v = {
68                #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
69                        (unsigned char)referenceCost,                   // low priority
70                        (unsigned char)(specCost + correctb),   // correct for signedness
71                        (unsigned char)varCost,
72                        (unsigned char)signCost,
73                        (unsigned char)safeCost,
74                        (unsigned char)polyCost,
75                        (unsigned char)implicitCost,
76                        (unsigned char)unsafeCost,                              // high priority
77                #else
78                        #error Cost BIG_ENDIAN unsupported
79                #endif
80                };
81        }
82
83        int get_unsafeCost() const { return v.unsafeCost; }
84        int get_implictCost() const { return v.implicitCost; }
85        int get_polyCost() const { return v.polyCost; }
86        int get_safeCost() const { return v.safeCost; }
87        int get_signCost() const { return v.signCost; }
88        int get_varCost() const { return v.varCost; }
89        int get_specCost() const { return -(correctb - v.specCost); }
90        int get_referenceCost() const { return v.referenceCost; }
91
92        friend bool operator==( const Cost, const Cost );
93        friend bool operator!=( const Cost lhs, const Cost rhs );
94        // returns negative for *this < rhs, 0 for *this == rhs, positive for *this > rhs
95        int compare( const Cost rhs ) const {
96                if ( all == infinity ) return 1;
97                if ( rhs.all == infinity ) return -1;
98                return all > rhs.all ? 1 : all == rhs.all ? 0 : -1;
99        }
100        friend bool operator<( const Cost lhs, const Cost rhs );
101
102        friend Cost operator+( const Cost lhs, const Cost rhs );
103
104        Cost operator+=( const Cost rhs ) {
105                if ( all == infinity ) return *this;
106                if ( rhs.all == infinity ) {
107                        all = infinity;
108                        return *this;
109                }
110                all += rhs.all - correctw;                                      // correct for negative spec cost
111                return *this;
112        }
113
114        Cost incUnsafe( int inc = 1 ) {
115                if ( all != infinity ) { assert( v.unsafeCost + inc <= UCHAR_MAX ); v.unsafeCost += inc; }
116                return *this;
117        }
118
119        Cost incImplicit( int inc = 1 ) {
120                if ( all != infinity ) { assert( v.implicitCost + inc <= UCHAR_MAX ); v.implicitCost += inc; }
121                return *this;
122        }
123
124        Cost incPoly( int inc = 1 ) {
125                if ( all != infinity ) { assert( v.polyCost + inc <= UCHAR_MAX ); v.polyCost += inc; }
126                return *this;
127        }
128
129        Cost incSafe( int inc = 1 ) {
130                if ( all != infinity ) { assert( v.safeCost + inc <= UCHAR_MAX ); v.safeCost += inc; }
131                return *this;
132        }
133
134        Cost incSign( int inc = 1 ) {
135                if ( all != infinity ) { assert( v.signCost + inc <= UCHAR_MAX ); v.signCost += inc; }
136                return *this;
137        }
138
139        Cost incVar( int inc = 1 ) {
140                if ( all != infinity ) { assert( v.varCost + inc <= UCHAR_MAX ); v.varCost += inc; }
141                return *this;
142        }
143
144        Cost decSpec( int dec = 1 ) {
145                if ( all != infinity ) { assert( v.specCost - dec >= 0 ); v.specCost -= dec; }
146                return *this;
147        }
148
149        Cost incReference( int inc = 1 ) {
150                if ( all != infinity ) { assert( v.referenceCost + inc <= UCHAR_MAX ); v.referenceCost += inc; }
151                return *this;
152        }
153
154        friend std::ostream & operator<<( std::ostream & os, const Cost cost );
155};
156
157inline bool operator==( const Cost lhs, const Cost rhs ) {
158        return lhs.all == rhs.all;
159}
160
161inline bool operator!=( const Cost lhs, const Cost rhs ) {
162        return !( lhs.all == rhs.all );
163}
164
165inline bool operator<( const Cost lhs, const Cost rhs ) {
166        if ( lhs.all == Cost::infinity ) return false;
167        if ( rhs.all == Cost::infinity ) return true;
168        return lhs.all < rhs.all;
169}
170
171inline Cost operator+( const Cost lhs, const Cost rhs ) {
172        if ( lhs.all == Cost::infinity || rhs.all == Cost::infinity ) return Cost{ Cost::infinity };
173        return Cost{ lhs.all + rhs.all - Cost::correctw }; // correct for negative spec cost
174}
175
176inline std::ostream & operator<<( std::ostream & os, const Cost cost ) {
177        return os << "( " << cost.get_unsafeCost() << ", " << cost.get_implictCost() << ", " << cost.get_polyCost() << ", " << cost.get_safeCost()
178                          << ", " << cost.get_signCost() << ", " << cost.get_varCost() << ", " << cost.get_specCost()
179                          << ", " << cost.get_referenceCost() << " )";
180}
181
182} // namespace ResolvExpr
183
184// Local Variables: //
185// tab-width: 4 //
186// mode: c++ //
187// compile-command: "make install" //
188// End: //
Note: See TracBrowser for help on using the repository browser.