LLVM 23.0.0git
InstructionCost.h
Go to the documentation of this file.
1//===- InstructionCost.h ----------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8/// \file
9/// This file defines an InstructionCost class that is used when calculating
10/// the cost of an instruction, or a group of instructions. In addition to a
11/// numeric value representing the cost the class also contains a state that
12/// can be used to encode particular properties, such as a cost being invalid.
13/// Operations on InstructionCost implement saturation arithmetic, so that
14/// accumulating costs on large cost-values don't overflow.
15///
16//===----------------------------------------------------------------------===//
17
18#ifndef LLVM_SUPPORT_INSTRUCTIONCOST_H
19#define LLVM_SUPPORT_INSTRUCTIONCOST_H
20
23#include <limits>
24#include <tuple>
25
26namespace llvm {
27
28class raw_ostream;
29
31public:
32 using CostType = int64_t;
33
34 /// CostState describes the state of a cost.
35 enum CostState {
36 Valid, /// < The cost value represents a valid cost, even when the
37 /// cost-value is large.
38 Invalid /// < Invalid indicates there is no way to represent the cost as a
39 /// numeric value. This state exists to represent a possible issue,
40 /// e.g. if the cost-model knows the operation cannot be expanded
41 /// into a valid code-sequence by the code-generator. While some
42 /// passes may assert that the calculated cost must be valid, it is
43 /// up to individual passes how to interpret an Invalid cost. For
44 /// example, a transformation pass could choose not to perform a
45 /// transformation if the resulting cost would end up Invalid.
46 /// Because some passes may assert a cost is Valid, it is not
47 /// recommended to use Invalid costs to model 'Unknown'.
48 /// Note that Invalid is semantically different from a (very) high,
49 /// but valid cost, which intentionally indicates no issue, but
50 /// rather a strong preference not to select a certain operation.
51 };
52
53private:
54 CostType Value = 0;
55 CostState State = Valid;
56
57 void propagateState(const InstructionCost &RHS) {
58 if (RHS.State == Invalid)
59 State = Invalid;
60 }
61
62 // Matches GCC, can use shift rather than multiply/divide to scale
63 static constexpr CostType CostGranularity = 4;
64
65 static constexpr CostType MaxValue = std::numeric_limits<CostType>::max();
66 static constexpr CostType MinValue = std::numeric_limits<CostType>::min();
67
68public:
69 // A default constructed InstructionCost is a valid zero cost
70 InstructionCost() = default;
71
73 InstructionCost(CostType Val) : Value(), State(Valid) {
75 if (MulOverflow(Val, CostGranularity, Result))
76 Result = Val > 0 ? MaxValue : MinValue;
77 Value = Result;
78 }
79
80 static InstructionCost getMax() { return MaxValue; }
81 static InstructionCost getMin() { return MinValue; }
83 InstructionCost Tmp(Val);
84 Tmp.setInvalid();
85 return Tmp;
86 }
87
88 bool isValid() const { return State == Valid; }
89 void setValid() { State = Valid; }
90 void setInvalid() { State = Invalid; }
91 CostState getState() const { return State; }
92
93 /// This function is intended to be used as sparingly as possible, since the
94 /// class provides the full range of operator support required for arithmetic
95 /// and comparisons.
97 assert(isValid());
98 return Value / CostGranularity;
99 }
100
101 /// For all of the arithmetic operators provided here any invalid state is
102 /// perpetuated and cannot be removed. Once a cost becomes invalid it stays
103 /// invalid, and it also inherits any invalid state from the RHS.
104 /// Arithmetic work on the actual values is implemented with saturation,
105 /// to avoid overflow when using more extreme cost values.
106
108 propagateState(RHS);
109
110 // Saturating addition.
112 if (AddOverflow(Value, RHS.Value, Result))
113 Result = RHS.Value > 0 ? MaxValue : MinValue;
114
115 Value = Result;
116 return *this;
117 }
118
120 InstructionCost RHS2(RHS);
121 *this += RHS2;
122 return *this;
123 }
124
126 propagateState(RHS);
127
128 // Saturating subtract.
130 if (SubOverflow(Value, RHS.Value, Result))
131 Result = RHS.Value > 0 ? MinValue : MaxValue;
132 Value = Result;
133 return *this;
134 }
135
137 InstructionCost RHS2(RHS);
138 *this -= RHS2;
139 return *this;
140 }
141
143 propagateState(RHS);
144
145 // Saturating multiply.
147 if (MulOverflow(Value, RHS.Value, Result)) {
148 if ((Value > 0 && RHS.Value > 0) || (Value < 0 && RHS.Value < 0))
149 Result = MaxValue;
150 else
151 Result = MinValue;
152 } else {
153 Result /= CostGranularity;
154 }
155
156 Value = Result;
157 return *this;
158 }
159
161 InstructionCost RHS2(RHS);
162 *this *= RHS2;
163 return *this;
164 }
165
167 propagateState(RHS);
168 // Saturating multiply.
170 if (MulOverflow(Value, CostGranularity, Result))
171 Result = Value > 0 ? MaxValue : MinValue;
172 Result /= RHS.Value;
173 Value = Result;
174 return *this;
175 }
176
178 Value /= RHS;
179 return *this;
180 }
181
183 *this += 1;
184 return *this;
185 }
186
188 InstructionCost Copy = *this;
189 ++*this;
190 return Copy;
191 }
192
194 *this -= 1;
195 return *this;
196 }
197
199 InstructionCost Copy = *this;
200 --*this;
201 return Copy;
202 }
203
204 /// For the comparison operators we have chosen to use lexicographical
205 /// ordering where valid costs are always considered to be less than invalid
206 /// costs. This avoids having to add asserts to the comparison operators that
207 /// the states are valid and users can test for validity of the cost
208 /// explicitly.
209 bool operator<(const InstructionCost &RHS) const {
210 return std::tie(State, Value) < std::tie(RHS.State, RHS.Value);
211 }
212
213 bool operator==(const InstructionCost &RHS) const {
214 return State == RHS.State && Value == RHS.Value;
215 }
216
217 bool operator!=(const InstructionCost &RHS) const { return !(*this == RHS); }
218
219 bool operator==(const CostType RHS) const {
220 InstructionCost RHS2(RHS);
221 return *this == RHS2;
222 }
223
224 bool operator!=(const CostType RHS) const { return !(*this == RHS); }
225
226 bool operator>(const InstructionCost &RHS) const { return RHS < *this; }
227
228 bool operator<=(const InstructionCost &RHS) const { return !(RHS < *this); }
229
230 bool operator>=(const InstructionCost &RHS) const { return !(*this < RHS); }
231
232 bool operator<(const CostType RHS) const {
233 InstructionCost RHS2(RHS);
234 return *this < RHS2;
235 }
236
237 bool operator>(const CostType RHS) const {
238 InstructionCost RHS2(RHS);
239 return *this > RHS2;
240 }
241
242 bool operator<=(const CostType RHS) const {
243 InstructionCost RHS2(RHS);
244 return *this <= RHS2;
245 }
246
247 bool operator>=(const CostType RHS) const {
248 InstructionCost RHS2(RHS);
249 return *this >= RHS2;
250 }
251
252 LLVM_ABI void print(raw_ostream &OS) const;
253
254 template <class Function>
255 auto map(const Function &F) const -> InstructionCost {
256 if (isValid())
257 return F(Value);
258 return getInvalid();
259 }
260};
261
263 const InstructionCost &RHS) {
264 InstructionCost LHS2(LHS);
265 LHS2 += RHS;
266 return LHS2;
267}
268
270 const InstructionCost &RHS) {
271 InstructionCost LHS2(LHS);
272 LHS2 -= RHS;
273 return LHS2;
274}
275
277 const InstructionCost &RHS) {
278 InstructionCost LHS2(LHS);
279 LHS2 *= RHS;
280 return LHS2;
281}
282
284 const InstructionCost &RHS) {
285 InstructionCost LHS2(LHS);
286 LHS2 /= RHS;
287 return LHS2;
288}
289
291 V.print(OS);
292 return OS;
293}
294
295} // namespace llvm
296
297#endif
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define LLVM_ABI
Definition Compiler.h:213
#define F(x, y, z)
Definition MD5.cpp:54
Value * RHS
Value * LHS
InstructionCost & operator+=(const CostType RHS)
bool operator!=(const CostType RHS) const
bool operator==(const InstructionCost &RHS) const
InstructionCost & operator*=(const InstructionCost &RHS)
auto map(const Function &F) const -> InstructionCost
InstructionCost & operator--()
InstructionCost & operator++()
static InstructionCost getMin()
InstructionCost operator++(int)
static InstructionCost getInvalid(CostType Val=0)
InstructionCost & operator-=(const CostType RHS)
LLVM_ABI void print(raw_ostream &OS) const
bool operator>(const InstructionCost &RHS) const
InstructionCost operator--(int)
static InstructionCost getMax()
InstructionCost & operator+=(const InstructionCost &RHS)
For all of the arithmetic operators provided here any invalid state is perpetuated and cannot be remo...
bool operator>=(const CostType RHS) const
bool operator<=(const CostType RHS) const
bool operator!=(const InstructionCost &RHS) const
InstructionCost & operator-=(const InstructionCost &RHS)
CostState
CostState describes the state of a cost.
@ Invalid
< The cost value represents a valid cost, even when the cost-value is large.
InstructionCost & operator/=(const InstructionCost &RHS)
bool operator>=(const InstructionCost &RHS) const
InstructionCost(CostType Val)
bool operator<(const InstructionCost &RHS) const
For the comparison operators we have chosen to use lexicographical ordering where valid costs are alw...
InstructionCost & operator*=(const CostType RHS)
InstructionCost(CostState)=delete
bool operator==(const CostType RHS) const
bool operator<=(const InstructionCost &RHS) const
bool operator<(const CostType RHS) const
bool operator>(const CostType RHS) const
CostType getValue() const
This function is intended to be used as sparingly as possible, since the class provides the full rang...
CostState getState() const
InstructionCost & operator/=(const CostType RHS)
LLVM Value Representation.
Definition Value.h:75
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
This is an optimization pass for GlobalISel generic memory operations.
std::enable_if_t< std::is_signed_v< T >, T > MulOverflow(T X, T Y, T &Result)
Multiply two signed integers, computing the two's complement truncated result, returning true if an o...
Definition MathExtras.h:753
APInt operator*(APInt a, uint64_t RHS)
Definition APInt.h:2264
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
APInt operator-(APInt)
Definition APInt.h:2217
std::enable_if_t< std::is_signed_v< T >, T > AddOverflow(T X, T Y, T &Result)
Add two signed integers, computing the two's complement truncated result, returning true if overflow ...
Definition MathExtras.h:701
APInt operator+(APInt a, const APInt &b)
Definition APInt.h:2222
std::enable_if_t< std::is_signed_v< T >, T > SubOverflow(T X, T Y, T &Result)
Subtract two signed integers, computing the two's complement truncated result, returning true if an o...
Definition MathExtras.h:727
LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt operator/(const DynamicAPInt &A, int64_t B)