19
19
#include " llvm/MC/MCInst.h"
20
20
#include " llvm/Support/Format.h"
21
21
22
- #include < limits >
22
+ #include < functional >
23
23
24
24
#define DEBUG_TYPE " bolt-stackclash"
25
25
@@ -70,51 +70,85 @@ bool addToMaxMap(SmallDenseMap<MCPhysReg, uint64_t, 1> &M, MCPhysReg R,
70
70
}
71
71
}
72
72
73
- class MaxOffsetT {
73
+ template < typename T, auto MergeValLambda> class LatticeT {
74
74
private:
75
- int64_t V ;
76
- // FIXME: should I add an "iteration count", and allow
77
- // "max" to be computed a few times. But if it's being
78
- // computed too many times, give up?
79
-
75
+ enum LValType { _Bottom, _Top, Value } LValType ;
76
+ T V;
77
+ LatticeT ( enum LValType ValType, T Val) : LValType(ValType), V(Val) {}
78
+ static LatticeT _TopV; // (_Top, T());
79
+ static LatticeT _BottomV; // (_Bottom, T());
80
80
public:
81
- MaxOffsetT () : V(Bottom().V) {}
82
- MaxOffsetT (int64_t O) : V(O) {}
83
- static MaxOffsetT Top () { return std::numeric_limits<int64_t >::max (); }
84
- static MaxOffsetT Bottom () { return std::numeric_limits<int64_t >::min (); }
85
- static MaxOffsetT doConfluence (const MaxOffsetT O1, const MaxOffsetT O2) {
86
- if (O1 == O2)
87
- return O1;
88
- if (O1 == Bottom ())
89
- return O2;
90
- if (O2 == Bottom ())
91
- return O1;
92
- return Top ();
81
+ LatticeT () : LatticeT(_Bottom, T()) {}
82
+ LatticeT (T V) : LatticeT(Value, V) {}
83
+ static const LatticeT &Top () { return _TopV; }
84
+ static const LatticeT &Bottom () { return _BottomV; }
85
+ LatticeT &operator &=(const LatticeT &E2 ) {
86
+ switch (E2 .LValType ) {
87
+ case _Bottom:
88
+ // nothing to do.
89
+ break ;
90
+ case _Top:
91
+ *this = Top ();
92
+ break ;
93
+ case Value:
94
+ switch (LValType) {
95
+ case _Bottom:
96
+ *this = E2 ;
97
+ break ;
98
+ case _Top:
99
+ // nothing to do.
100
+ break ;
101
+ case Value:
102
+ if (!MergeValLambda (V, E2 .V ))
103
+ *this = Top ();
104
+ break ;
105
+ }
106
+ break ;
107
+ }
108
+ return *this ;
93
109
}
94
- MaxOffsetT operator +(const int64_t Offset) const {
95
- assert (*this != Bottom ());
96
- if (*this == Top ())
97
- return Top ();
98
- return MaxOffsetT (V + Offset);
110
+ bool operator ==(const LatticeT &RHS) const {
111
+ return LValType == RHS.LValType && V == RHS.V ;
99
112
}
100
- bool operator ==(const MaxOffsetT RHS) const { return V == RHS.V ; }
101
- bool operator !=(const MaxOffsetT RHS) const { return !(*this == RHS); }
102
- int64_t getIntValue () const {
113
+ bool operator !=(const LatticeT &RHS) const { return !(*this == RHS); }
114
+ const T &getVal () const {
103
115
assert (*this != Bottom () && *this != Top ());
104
116
return V;
105
117
}
118
+ LatticeT &doOnVal (std::function<const T &(T &, const T &)> f, const T &V2) {
119
+ assert (*this != Bottom ());
120
+ if (*this == Top ())
121
+ return *this ;
122
+ V = f (V, V2);
123
+ return *this ;
124
+ }
106
125
};
107
126
108
- raw_ostream &operator <<(raw_ostream &OS, MaxOffsetT O) {
109
- if (O == MaxOffsetT::Top ())
127
+ template <typename T, auto M> LatticeT<T, M> LatticeT<T, M>::_TopV(_Top, T());
128
+ template <typename T, auto M>
129
+ LatticeT<T, M> LatticeT<T, M>::_BottomV(_Bottom, T());
130
+
131
+ template <typename T, auto M>
132
+ raw_ostream &operator <<(raw_ostream &OS, const LatticeT<T, M> &V) {
133
+ if (V == V.Top ())
110
134
OS << " (T)" ;
111
- else if (O == MaxOffsetT:: Bottom ())
135
+ else if (V == V. Bottom ())
112
136
OS << " (B)" ;
113
137
else
114
- OS << O. getIntValue ();
138
+ OS << V. getVal ();
115
139
return OS;
116
140
}
117
141
142
+ bool MaxOffsetMergeVal (int64_t &v1, const int64_t &v2) { return v1 == v2; }
143
+ using MaxOffsetT = LatticeT<int64_t , MaxOffsetMergeVal>;
144
+ const auto AddOffset = [](int64_t &v1, const int64_t &v2) -> const int64_t & {
145
+ v1 += v2;
146
+ return v1;
147
+ };
148
+ MaxOffsetT &operator +=(MaxOffsetT &O1, const int64_t O2) {
149
+ return O1.doOnVal (AddOffset, O2);
150
+ }
151
+
118
152
struct State {
119
153
// Store the maximum possible offset to which the stack extends
120
154
// beyond the furthest probe seen.
@@ -124,6 +158,8 @@ struct State {
124
158
SmallDenseMap<MCPhysReg, uint64_t , 1 > RegConstValues;
125
159
// / RegMaxValues stores registers that we know have a value in the
126
160
// / range [0, MaxValue-1].
161
+ // FIXME: also make this std::optional!!!
162
+ // FIXME: same for RegConstValues.
127
163
SmallDenseMap<MCPhysReg, uint64_t , 1 > RegMaxValues;
128
164
// / Reg2MaxOffset contains the registers that contain the value
129
165
// / of SP at some point during the running function, where it's
@@ -176,6 +212,8 @@ struct State {
176
212
else
177
213
Reg2MaxValue.second =
178
214
std::max (Reg2MaxValue.second , SInReg2MaxValue->second );
215
+ // FIXME: this should be a "confluence" - similar
216
+ // to MaxOffsetT? To avoid near infinite loops?
179
217
}
180
218
for (MCPhysReg R : RegMaxValuesToRemove)
181
219
RegMaxValues.erase (R);
@@ -186,20 +224,20 @@ struct State {
186
224
SPFixedOffsetFromOrig.reset ();
187
225
188
226
if (StateIn.Reg2MaxOffset && Reg2MaxOffset) {
189
- SmallDenseMap <MCPhysReg, MaxOffsetT, 2 > MergedMap ;
227
+ SmallVector <MCPhysReg, 2 > RToRemove ;
190
228
for (auto R2MaxOff : *Reg2MaxOffset) {
191
229
const MCPhysReg R = R2MaxOff.first ;
192
230
if (auto SIn_R2MaxOff = StateIn.Reg2MaxOffset ->find (R);
193
- SIn_R2MaxOff != StateIn.Reg2MaxOffset ->end ()) {
231
+ SIn_R2MaxOff == StateIn.Reg2MaxOffset ->end ())
232
+ RToRemove.push_back (R);
233
+ else {
194
234
MaxOffsetT MaxOff1 = R2MaxOff.second ;
195
235
MaxOffsetT MaxOff2 = SIn_R2MaxOff->second ;
196
- MergedMap[R] = MaxOffsetT::doConfluence (MaxOff1, MaxOff2);
197
- #if 0
198
- std::max(R2MaxOff.second, SIn_R2MaxOff->second);
199
- #endif
236
+ MaxOff1 &= MaxOff2;
200
237
}
238
+ for (auto R : RToRemove)
239
+ Reg2MaxOffset->erase (R);
201
240
}
202
- Reg2MaxOffset = MergedMap;
203
241
} else if (StateIn.Reg2MaxOffset && !Reg2MaxOffset) {
204
242
Reg2MaxOffset = StateIn.Reg2MaxOffset ;
205
243
}
@@ -333,13 +371,14 @@ bool checkNonConstSPOffsetChange(const BinaryContext &BC, BinaryFunction &BF,
333
371
if (MaxOffset != MaxOffsetT::Top ()) {
334
372
if (Next) {
335
373
Next->MaxOffsetSinceLastProbe =
336
- MaxOffset.getIntValue () - *OC.OffsetChange ;
374
+ MaxOffset.getVal () - *OC.OffsetChange ;
337
375
Next->SPFixedOffsetFromOrig = std::nullopt;
338
376
}
339
377
} else {
340
378
// unlimited Max Offset
341
379
if (Next) {
342
- Next->MaxOffsetSinceLastProbe = std::numeric_limits<int64_t >::max ();// MaxOffsetT::Top();
380
+ Next->MaxOffsetSinceLastProbe =
381
+ std::numeric_limits<int64_t >::max (); // MaxOffsetT::Top();
343
382
Next->SPFixedOffsetFromOrig = std::nullopt;
344
383
}
345
384
IsNonConstantSPOffsetChange = true ;
@@ -358,11 +397,11 @@ bool checkNonConstSPOffsetChange(const BinaryContext &BC, BinaryFunction &BF,
358
397
int64_t MaxOffsetChange = BitsToZeroMask + 1 ;
359
398
IsNonConstantSPOffsetChange = false ;
360
399
MaxOffsetT MaxOffset = Cur.Reg2MaxOffset ->find (FromReg)->second ;
361
- MaxOffsetT NextOffset = MaxOffset + MaxOffsetChange;
362
- if (NextOffset == MaxOffsetT::Top ())
400
+ MaxOffset += MaxOffsetChange;
401
+ if (MaxOffset == MaxOffsetT::Top ())
363
402
IsNonConstantSPOffsetChange = true ;
364
403
else if (Next) {
365
- Next->MaxOffsetSinceLastProbe = NextOffset. getIntValue ();
404
+ Next->MaxOffsetSinceLastProbe = MaxOffset. getVal ();
366
405
Next->SPFixedOffsetFromOrig = std::nullopt;
367
406
}
368
407
}
@@ -505,12 +544,14 @@ class StackClashDFAnalysis
505
544
if (Next.Reg2MaxOffset && OC.OffsetChange ) {
506
545
int64_t Offset = *OC.OffsetChange ;
507
546
if (OC.FromReg == SP) {
508
- (*Next.Reg2MaxOffset )[OC.ToReg ] =
509
- *Cur.MaxOffsetSinceLastProbe + (-Offset);
547
+ MaxOffsetT &MaxOffset = (*Next.Reg2MaxOffset )[OC.ToReg ] =
548
+ *Cur.MaxOffsetSinceLastProbe ;
549
+ MaxOffset += (-Offset);
510
550
FixedOffsetRegJustSet = OC.ToReg ;
511
551
} else if (auto I = Cur.Reg2MaxOffset ->find (OC.FromReg );
512
552
I != Cur.Reg2MaxOffset ->end ()) {
513
- (*Next.Reg2MaxOffset )[OC.ToReg ] = (*I).second + (-Offset);
553
+ MaxOffsetT &MaxOffset = (*Next.Reg2MaxOffset )[OC.ToReg ] = (*I).second ;
554
+ MaxOffset += (-Offset);
514
555
FixedOffsetRegJustSet = OC.ToReg ;
515
556
}
516
557
}
0 commit comments