@@ -57,26 +57,15 @@ namespace {
57
57
// Step 1 - let's start by implementing detecting an issue on a bare minimal
58
58
// example. Therefore, implement (2), (3), (4) and (a).
59
59
60
- // / Returns true if the register R is present in the Map M.
61
- bool addToMaxMap (SmallDenseMap<MCPhysReg, uint64_t , 1 > &M, MCPhysReg R,
62
- const uint64_t MaxValue) {
63
- auto MIt = M.find (R);
64
- if (MIt == M.end ()) {
65
- MIt->second = MaxValue;
66
- return false ;
67
- } else {
68
- MIt->second = std::max (MIt->second , MaxValue);
69
- return true ;
70
- }
71
- }
72
-
73
60
template <typename T, auto MergeValLambda> class LatticeT {
74
61
private:
75
62
enum LValType { _Bottom, Value, _Top } LValType;
76
63
T V;
77
64
LatticeT (enum LValType ValType, T Val) : LValType(ValType), V(Val) {}
78
65
static LatticeT _TopV; // (_Top, T());
79
66
static LatticeT _BottomV; // (_Bottom, T());
67
+ static T _DefaultVal;
68
+
80
69
public:
81
70
LatticeT () : LatticeT(_Bottom, T()) {}
82
71
LatticeT (T V) : LatticeT(Value, V) {}
@@ -143,22 +132,22 @@ template <typename T, auto MergeValLambda> class LatticeT {
143
132
V = f (V, V2);
144
133
return *this ;
145
134
}
135
+ const T &getValOrDefault () const {
136
+ if (hasVal ())
137
+ return getVal ();
138
+ else
139
+ return _DefaultVal;
140
+ }
146
141
};
147
142
148
- template < typename T, auto M> LatticeT<T, M> LatticeT<T, M>::_TopV(_Top, T());
143
+
149
144
template <typename T, auto M>
150
- LatticeT<T, M> LatticeT<T, M>::_BottomV(_Bottom, T() );
145
+ raw_ostream & operator <<(raw_ostream &OS, const LatticeT<T, M> &V );
151
146
147
+ template <typename T, auto M> LatticeT<T, M> LatticeT<T, M>::_TopV(_Top, T());
152
148
template <typename T, auto M>
153
- raw_ostream &operator <<(raw_ostream &OS, const LatticeT<T, M> &V) {
154
- if (V == V.Top ())
155
- OS << " (T)" ;
156
- else if (V == V.Bottom ())
157
- OS << " (B)" ;
158
- else
159
- OS << V.getVal ();
160
- return OS;
161
- }
149
+ LatticeT<T, M> LatticeT<T, M>::_BottomV(_Bottom, T());
150
+ template <typename T, auto M> T LatticeT<T, M>::_DefaultVal = T();
162
151
163
152
bool MaxOffsetMergeVal (int64_t &v1, const int64_t &v2) { return v1 == v2; }
164
153
using MaxOffsetT = LatticeT<int64_t , MaxOffsetMergeVal>;
@@ -209,6 +198,55 @@ raw_ostream &operator<<(raw_ostream &OS, const Reg2MaxOffsetValT &M) {
209
198
210
199
using Reg2MaxOffsetT = LatticeT<Reg2MaxOffsetValT, Reg2MaxOffsetMergeVal>;
211
200
201
+ using Reg2MaxValT = SmallDenseMap<MCPhysReg, uint64_t , 1 >;
202
+ bool RegMaxValuesValMerge (Reg2MaxValT &v1, const Reg2MaxValT &v2) {
203
+ SmallVector<MCPhysReg, 1 > RegMaxValuesToRemove;
204
+ for (auto Reg2MaxValue : v1) {
205
+ const MCPhysReg R (Reg2MaxValue.first );
206
+ auto v2Reg2MaxValue = v2.find (R);
207
+ if (v2Reg2MaxValue == v2.end ())
208
+ RegMaxValuesToRemove.push_back (R);
209
+ else
210
+ Reg2MaxValue.second =
211
+ std::max (Reg2MaxValue.second , v2Reg2MaxValue->second );
212
+ // FIXME: this should be a "confluence" - similar
213
+ // to MaxOffsetT? To avoid near infinite loops?
214
+ }
215
+ for (MCPhysReg R : RegMaxValuesToRemove)
216
+ v1.erase (R);
217
+ return true ;
218
+ }
219
+ raw_ostream &operator <<(raw_ostream &OS, const Reg2MaxValT &M) {
220
+ for (auto Reg2Value : M) {
221
+ print_reg (OS, Reg2Value.first , nullptr );
222
+ OS << " :" << Reg2Value.second << " ," ;
223
+ }
224
+ return OS;
225
+ }
226
+ using RegMaxValuesT = LatticeT<Reg2MaxValT, RegMaxValuesValMerge>;
227
+
228
+ void addToMaxMap (RegMaxValuesT &M, MCPhysReg R, const uint64_t Value) {
229
+ if (!M.hasVal ())
230
+ return ;
231
+ auto MIt = M->find (R);
232
+ if (MIt == M->end ())
233
+ MIt->second = Value;
234
+ else
235
+ MIt->second = std::max (MIt->second , Value);
236
+ }
237
+
238
+ template <typename T, auto M>
239
+ raw_ostream &operator <<(raw_ostream &OS, const LatticeT<T, M> &V) {
240
+ if (V == V.Top ())
241
+ OS << " (T)" ;
242
+ else if (V == V.Bottom ())
243
+ OS << " (B)" ;
244
+ else
245
+ OS << V.getVal ();
246
+ return OS;
247
+ }
248
+
249
+
212
250
struct State {
213
251
// Store the maximum possible offset to which the stack extends
214
252
// beyond the furthest probe seen.
@@ -220,7 +258,7 @@ struct State {
220
258
// / range [0, MaxValue-1].
221
259
// FIXME: also make this std::optional!!!
222
260
// FIXME: same for RegConstValues.
223
- SmallDenseMap<MCPhysReg, uint64_t , 1 > RegMaxValues;
261
+ RegMaxValuesT RegMaxValues;
224
262
// / Reg2MaxOffset contains the registers that contain the value
225
263
// / of SP at some point during the running function, where it's
226
264
// / guaranteed that at the time the SP value was stored in the register,
@@ -263,20 +301,7 @@ struct State {
263
301
for (MCPhysReg R : RegConstValuesToRemove)
264
302
RegConstValues.erase (R);
265
303
266
- SmallVector<MCPhysReg, 1 > RegMaxValuesToRemove;
267
- for (auto Reg2MaxValue : RegMaxValues) {
268
- const MCPhysReg R (Reg2MaxValue.first );
269
- auto SInReg2MaxValue = StateIn.RegMaxValues .find (R);
270
- if (SInReg2MaxValue == StateIn.RegMaxValues .end ())
271
- RegMaxValuesToRemove.push_back (R);
272
- else
273
- Reg2MaxValue.second =
274
- std::max (Reg2MaxValue.second , SInReg2MaxValue->second );
275
- // FIXME: this should be a "confluence" - similar
276
- // to MaxOffsetT? To avoid near infinite loops?
277
- }
278
- for (MCPhysReg R : RegMaxValuesToRemove)
279
- RegMaxValues.erase (R);
304
+ RegMaxValues &= StateIn.RegMaxValues ;
280
305
281
306
if (!SPFixedOffsetFromOrig || !StateIn.SPFixedOffsetFromOrig )
282
307
SPFixedOffsetFromOrig.reset ();
@@ -318,13 +343,18 @@ raw_ostream &print_state(raw_ostream &OS, const State &S,
318
343
OS << " ), RegConstValues(" ;
319
344
PrintRegMap (OS, S.RegConstValues , BC);
320
345
OS << " ), RegMaxValues(" ;
321
- PrintRegMap (OS, S.RegMaxValues , BC);
346
+ if (S.RegMaxValues .hasVal ()) {
347
+ OS << " (" ;
348
+ PrintRegMap (OS, *S.RegMaxValues , BC);
349
+ OS << " )" ;
350
+ } else
351
+ OS << S.RegMaxValues ;
322
352
OS << " )," ;
323
353
OS << " SPFixedOffsetFromOrig:" << S.SPFixedOffsetFromOrig << " ," ;
324
354
OS << " Reg2MaxOffset:" ;
325
355
if (S.Reg2MaxOffset .hasVal ()) {
326
356
OS << " (" ;
327
- PrintRegMap (OS, S.Reg2MaxOffset . getVal () , BC);
357
+ PrintRegMap (OS, * S.Reg2MaxOffset , BC);
328
358
OS << " )" ;
329
359
} else
330
360
OS << S.Reg2MaxOffset ;
@@ -363,7 +393,7 @@ bool checkNonConstSPOffsetChange(const BinaryContext &BC, BinaryFunction &BF,
363
393
if (Next)
364
394
Next->LastStackGrowingInsts .insert (MCInstInBBReference::get (&Point, BF));
365
395
if (auto OC = BC.MIB ->getOffsetChange (Point, Cur.RegConstValues ,
366
- Cur.RegMaxValues );
396
+ Cur.RegMaxValues . getValOrDefault () );
367
397
OC && OC.ToReg == SP) {
368
398
if (OC.FromReg == SP) {
369
399
IsNonConstantSPOffsetChange = false ;
@@ -464,8 +494,10 @@ class StackClashDFAnalysis
464
494
465
495
State getStartingStateAtBB (const BinaryBasicBlock &BB) {
466
496
State Next;
467
- if (BB.isEntryPoint ())
497
+ if (BB.isEntryPoint ()) {
468
498
Next.Reg2MaxOffset = Reg2MaxOffsetValT ();
499
+ Next.RegMaxValues = Reg2MaxValT ();
500
+ }
469
501
return Next;
470
502
}
471
503
@@ -527,12 +559,13 @@ class StackClashDFAnalysis
527
559
<< " ; MaxValueMask: " << MaxValueMask << " \n " ;
528
560
});
529
561
const uint64_t MaxValueInReg = MaxValueMask;
530
- auto MaxValueForRegI = Next.RegMaxValues .find (MaxValueReg);
531
- if (MaxValueForRegI == Next.RegMaxValues .end ())
532
- Next.RegMaxValues [MaxValueReg] = MaxValueInReg;
533
- else {
534
- MaxValueForRegI->second =
535
- std::min (MaxValueForRegI->second , MaxValueInReg);
562
+ if (Next.RegMaxValues .hasVal ()) {
563
+ if (auto MaxValueForRegI = Next.RegMaxValues ->find (MaxValueReg);
564
+ MaxValueForRegI == Next.RegMaxValues ->end ())
565
+ (*Next.RegMaxValues )[MaxValueReg] = MaxValueInReg;
566
+ else
567
+ MaxValueForRegI->second =
568
+ std::min (MaxValueForRegI->second , MaxValueInReg);
536
569
}
537
570
}
538
571
// FIXME properly handle register aliases below. E.g. a call
@@ -545,8 +578,8 @@ class StackClashDFAnalysis
545
578
#endif
546
579
for (const MCOperand &Operand : BC.MIB ->defOperands (Point)) {
547
580
assert (Operand.isReg ());
548
- if (Operand.getReg () != MaxValueReg)
549
- Next.RegMaxValues . erase (Operand.getReg ());
581
+ if (Next. RegMaxValues . hasVal () && Operand.getReg () != MaxValueReg)
582
+ Next.RegMaxValues -> erase (Operand.getReg ());
550
583
if (Operand.getReg () != ConstValueReg)
551
584
Next.RegConstValues .erase (Operand.getReg ());
552
585
}
@@ -572,7 +605,7 @@ class StackClashDFAnalysis
572
605
573
606
MCPhysReg FixedOffsetRegJustSet = BC.MIB ->getNoRegister ();
574
607
if (auto OC = BC.MIB ->getOffsetChange (Point, Cur.RegConstValues ,
575
- Cur.RegMaxValues ))
608
+ Cur.RegMaxValues . getValOrDefault () ))
576
609
if (Next.Reg2MaxOffset .hasVal () && OC.OffsetChange ) {
577
610
int64_t Offset = *OC.OffsetChange ;
578
611
if (OC.FromReg == SP) {
0 commit comments