-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
Copy pathIntBounds.h
160 lines (126 loc) · 6.78 KB
/
IntBounds.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#pragma once
class Value;
class IntConstantBounds;
typedef JsUtil::BaseHashSet<ValueRelativeOffset, JitArenaAllocator, PowerOf2SizePolicy, ValueNumber> RelativeIntBoundSet;
#pragma region IntBounds
class IntBounds sealed
{
private:
int constantLowerBound, constantUpperBound;
bool wasConstantUpperBoundEstablishedExplicitly;
RelativeIntBoundSet relativeLowerBounds, relativeUpperBounds;
protected:
IntBounds(const IntConstantBounds &constantBounds, const bool wasConstantUpperBoundEstablishedExplicitly, JitArenaAllocator *const allocator);
public:
static IntBounds *New(const IntConstantBounds &constantBounds, const bool wasConstantUpperBoundEstablishedExplicitly, JitArenaAllocator *const allocator);
IntBounds *Clone() const;
void Delete() const;
public:
void Verify() const;
private:
bool HasBounds() const;
public:
bool RequiresIntBoundedValueInfo(const ValueType valueType) const;
bool RequiresIntBoundedValueInfo() const;
public:
int ConstantLowerBound() const;
int ConstantUpperBound() const;
IntConstantBounds ConstantBounds() const;
bool WasConstantUpperBoundEstablishedExplicitly() const;
public:
const RelativeIntBoundSet &RelativeLowerBounds() const;
const RelativeIntBoundSet &RelativeUpperBounds() const;
public:
void SetLowerBound(const int constantBound);
void SetLowerBound(const int constantBoundBase, const int offset);
void SetUpperBound(const int constantBound, const bool wasEstablishedExplicitly);
void SetUpperBound(const int constantBoundBase, const int offset, const bool wasEstablishedExplicitly);
private:
template<bool Lower> void SetBound(const int constantBoundBase, const int offset, const bool wasEstablishedExplicitly);
public:
void SetLowerBound(const ValueNumber myValueNumber, const Value *const baseValue, const bool wasEstablishedExplicitly);
void SetLowerBound(const ValueNumber myValueNumber, const Value *const baseValue, const int offset, const bool wasEstablishedExplicitly);
void SetUpperBound(const ValueNumber myValueNumber, const Value *const baseValue, const bool wasEstablishedExplicitly);
void SetUpperBound(const ValueNumber myValueNumber, const Value *const baseValue, const int offset, const bool wasEstablishedExplicitly);
private:
template<bool Lower> void SetBound(const ValueNumber myValueNumber, const Value *const baseValue, const int offset, const bool wasEstablishedExplicitly);
public:
bool SetIsNot(const int constantValue, const bool isExplicit);
bool SetIsNot(const Value *const value, const bool isExplicit);
public:
static bool IsGreaterThanOrEqualTo(const int constantValue, const int constantBoundBase, const int offset);
static bool IsLessThanOrEqualTo(const int constantValue, const int constantBoundBase, const int offset);
public:
bool IsGreaterThanOrEqualTo(const int constantBoundBase, const int offset = 0) const;
bool IsLessThanOrEqualTo(const int constantBoundBase, const int offset = 0) const;
public:
bool IsGreaterThanOrEqualTo(const Value *const value, const int offset = 0) const;
bool IsLessThanOrEqualTo(const Value *const value, const int offset = 0) const;
public:
static const IntBounds *Add(const Value *const baseValue, const int n, const bool baseValueInfoIsPrecise, const IntConstantBounds &newConstantBounds, JitArenaAllocator *const allocator);
public:
bool AddCannotOverflowBasedOnRelativeBounds(const int n) const;
bool SubCannotOverflowBasedOnRelativeBounds(const int n) const;
public:
static const IntBounds *Merge(const Value *const bounds0Value, const IntBounds *const bounds0, const Value *const bounds1Value, const IntConstantBounds &constantBounds1);
static const IntBounds *Merge(const Value *const bounds0Value, const IntBounds *const bounds0, const Value *const bounds1Value, const IntBounds *const bounds1);
private:
template<bool Lower> static void MergeBoundSets(const Value *const bounds0Value, const IntBounds *const bounds0, const Value *const bounds1Value, const IntBounds *const bounds1, IntBounds *const mergedBounds);
PREVENT_ASSIGN(IntBounds);
};
#pragma endregion
#pragma region IntBoundCheckCompatibilityId and IntBoundCheck
// A bounds check takes the form (a <= b + offset). For instance, (i >= 0) would be represented as (0 <= i + 0), and (i < n)
// would be represented as (i <= n - 1). When a bounds check is required, from the two value numbers, it can be determined
// whether an existing, compatible bounds check can be updated by decreasing the offset aggressively instead of adding a new
// bounds check. The offset may only be decreased such that it does not invalidate the invariant previously established by the
// check.
//
// For instance, given that we have the bound checks (0 <= i + 0) and (i <= n - 1), suppose the bounds checks (i + 1 >= 0) and
// (i + 1 < n) are required. (i + 1 >= 0) would be represented as (0 <= i + 1). Given that (0 <= i + 0), it is already
// guaranteed that (0 <= i + 1), so no change is necessary for that part. (i + 1 < n) would be represented as (i <= n + 0). The
// compatible bounds check (i <= n - 1) would be found and updated aggressively to (i <= n + 0).
class IntBoundCheckCompatibilityId
{
private:
const ValueNumber leftValueNumber, rightValueNumber;
public:
IntBoundCheckCompatibilityId(const ValueNumber leftValueNumber, const ValueNumber rightValueNumber);
public:
bool operator ==(const IntBoundCheckCompatibilityId &other) const;
operator hash_t() const;
};
class IntBoundCheck
{
private:
ValueNumber leftValueNumber, rightValueNumber;
IR::Instr *instr;
BasicBlock *block;
public:
IntBoundCheck();
IntBoundCheck(const ValueNumber leftValueNumber, const ValueNumber rightValueNumber, IR::Instr *const instr, BasicBlock *const block);
#if DBG
public:
bool IsValid() const;
#endif
public:
ValueNumber LeftValueNumber() const;
ValueNumber RightValueNumber() const;
IR::Instr *Instr() const;
BasicBlock *Block() const;
IntBoundCheckCompatibilityId CompatibilityId() const;
public:
bool SetBoundOffset(const int offset, const bool isLoopCountBasedBound = false) const;
};
template<>
inline IntBoundCheckCompatibilityId JsUtil::ValueToKey<IntBoundCheckCompatibilityId, IntBoundCheck>::ToKey(
const IntBoundCheck &intBoundCheck)
{
return intBoundCheck.CompatibilityId();
}
typedef JsUtil::BaseHashSet<IntBoundCheck, JitArenaAllocator, PowerOf2SizePolicy, IntBoundCheckCompatibilityId> IntBoundCheckSet;
#pragma endregion