19
19
#include " llvm/MC/MCInst.h"
20
20
#include " llvm/Support/Format.h"
21
21
22
+ #include < limits>
23
+
22
24
#define DEBUG_TYPE " bolt-stackclash"
23
25
24
26
namespace llvm {
@@ -68,6 +70,51 @@ bool addToMaxMap(SmallDenseMap<MCPhysReg, uint64_t, 1> &M, MCPhysReg R,
68
70
}
69
71
}
70
72
73
+ class MaxOffsetT {
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
+
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 ();
93
+ }
94
+ MaxOffsetT operator +(const int64_t Offset) const {
95
+ assert (*this != Bottom ());
96
+ if (*this == Top ())
97
+ return Top ();
98
+ return MaxOffsetT (V + Offset);
99
+ }
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 {
103
+ assert (*this != Bottom () && *this != Top ());
104
+ return V;
105
+ }
106
+ };
107
+
108
+ raw_ostream &operator <<(raw_ostream &OS, MaxOffsetT O) {
109
+ if (O == MaxOffsetT::Top ())
110
+ OS << " (T)" ;
111
+ else if (O == MaxOffsetT::Bottom ())
112
+ OS << " (B)" ;
113
+ else
114
+ OS << O.getIntValue ();
115
+ return OS;
116
+ }
117
+
71
118
struct State {
72
119
// Store the maximum possible offset to which the stack extends
73
120
// beyond the furthest probe seen.
@@ -89,7 +136,7 @@ struct State {
89
136
// / This is only tracked in Basic Blocks that are known to be reachable
90
137
// / from an entry block. For blocks not (yet) known to be reachable from
91
138
// / an entry block, the optional does not contain a value.
92
- std::optional<SmallDenseMap<MCPhysReg, int64_t , 2 >> Reg2MaxOffset;
139
+ std::optional<SmallDenseMap<MCPhysReg, MaxOffsetT , 2 >> Reg2MaxOffset;
93
140
// FIXME: It seems that conceptually it does not make sense to
94
141
// track wheterh the SP value is currently at a fixed offset from
95
142
// the value it was at function entry.
@@ -139,12 +186,18 @@ struct State {
139
186
SPFixedOffsetFromOrig.reset ();
140
187
141
188
if (StateIn.Reg2MaxOffset && Reg2MaxOffset) {
142
- SmallDenseMap<MCPhysReg, int64_t , 2 > MergedMap;
189
+ SmallDenseMap<MCPhysReg, MaxOffsetT , 2 > MergedMap;
143
190
for (auto R2MaxOff : *Reg2MaxOffset) {
144
191
const MCPhysReg R = R2MaxOff.first ;
145
192
if (auto SIn_R2MaxOff = StateIn.Reg2MaxOffset ->find (R);
146
- SIn_R2MaxOff != StateIn.Reg2MaxOffset ->end ())
147
- MergedMap[R] = std::max (R2MaxOff.second , SIn_R2MaxOff->second );
193
+ SIn_R2MaxOff != StateIn.Reg2MaxOffset ->end ()) {
194
+ MaxOffsetT MaxOff1 = R2MaxOff.second ;
195
+ 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
200
+ }
148
201
}
149
202
Reg2MaxOffset = MergedMap;
150
203
} else if (StateIn.Reg2MaxOffset && !Reg2MaxOffset) {
@@ -266,8 +319,7 @@ bool checkNonConstSPOffsetChange(const BinaryContext &BC, BinaryFunction &BF,
266
319
<< " ; new MaxOffsetSinceLastProbe: "
267
320
<< Next->MaxOffsetSinceLastProbe
268
321
<< " ; new SPFixedOffsetFromOrig: "
269
- << Next->SPFixedOffsetFromOrig
270
- << " \n " ;
322
+ << Next->SPFixedOffsetFromOrig << " \n " ;
271
323
});
272
324
}
273
325
// assert(!OC.IsPreIndexOffsetChange || IsStackAccess);
@@ -276,10 +328,21 @@ bool checkNonConstSPOffsetChange(const BinaryContext &BC, BinaryFunction &BF,
276
328
} else if (Cur.Reg2MaxOffset && Cur.Reg2MaxOffset ->contains (OC.FromReg ) &&
277
329
OC.OffsetChange ) {
278
330
IsNonConstantSPOffsetChange = false ;
279
- const int64_t MaxOffset = Cur.Reg2MaxOffset ->find (OC.FromReg )->second ;
280
- if (Next) {
281
- Next->MaxOffsetSinceLastProbe = MaxOffset - *OC.OffsetChange ;
282
- Next->SPFixedOffsetFromOrig = std::nullopt;
331
+ const MaxOffsetT MaxOffset =
332
+ Cur.Reg2MaxOffset ->find (OC.FromReg )->second ;
333
+ if (MaxOffset != MaxOffsetT::Top ()) {
334
+ if (Next) {
335
+ Next->MaxOffsetSinceLastProbe =
336
+ MaxOffset.getIntValue () - *OC.OffsetChange ;
337
+ Next->SPFixedOffsetFromOrig = std::nullopt;
338
+ }
339
+ } else {
340
+ // unlimited Max Offset
341
+ if (Next) {
342
+ Next->MaxOffsetSinceLastProbe = std::numeric_limits<int64_t >::max ();// MaxOffsetT::Top();
343
+ Next->SPFixedOffsetFromOrig = std::nullopt;
344
+ }
345
+ IsNonConstantSPOffsetChange = true ;
283
346
}
284
347
}
285
348
}
@@ -293,12 +356,15 @@ bool checkNonConstSPOffsetChange(const BinaryContext &BC, BinaryFunction &BF,
293
356
// and sp, x9, #0xffffffffffffff80
294
357
uint64_t BitsToZeroMask = ~Mask;
295
358
int64_t MaxOffsetChange = BitsToZeroMask + 1 ;
296
- if (Next) {
297
- Next->MaxOffsetSinceLastProbe =
298
- Cur.Reg2MaxOffset ->find (FromReg)->second + MaxOffsetChange;
359
+ IsNonConstantSPOffsetChange = false ;
360
+ MaxOffsetT MaxOffset = Cur.Reg2MaxOffset ->find (FromReg)->second ;
361
+ MaxOffsetT NextOffset = MaxOffset + MaxOffsetChange;
362
+ if (NextOffset == MaxOffsetT::Top ())
363
+ IsNonConstantSPOffsetChange = true ;
364
+ else if (Next) {
365
+ Next->MaxOffsetSinceLastProbe = NextOffset.getIntValue ();
299
366
Next->SPFixedOffsetFromOrig = std::nullopt;
300
367
}
301
- IsNonConstantSPOffsetChange = false ;
302
368
}
303
369
304
370
return IsNonConstantSPOffsetChange;
@@ -328,7 +394,7 @@ class StackClashDFAnalysis
328
394
State getStartingStateAtBB (const BinaryBasicBlock &BB) {
329
395
State Next;
330
396
if (BB.isEntryPoint ())
331
- Next.Reg2MaxOffset = SmallDenseMap<MCPhysReg, int64_t , 2 >();
397
+ Next.Reg2MaxOffset = SmallDenseMap<MCPhysReg, MaxOffsetT , 2 >();
332
398
return Next;
333
399
}
334
400
@@ -440,11 +506,11 @@ class StackClashDFAnalysis
440
506
int64_t Offset = *OC.OffsetChange ;
441
507
if (OC.FromReg == SP) {
442
508
(*Next.Reg2MaxOffset )[OC.ToReg ] =
443
- *Cur.MaxOffsetSinceLastProbe - Offset;
509
+ *Cur.MaxOffsetSinceLastProbe + (- Offset) ;
444
510
FixedOffsetRegJustSet = OC.ToReg ;
445
511
} else if (auto I = Cur.Reg2MaxOffset ->find (OC.FromReg );
446
512
I != Cur.Reg2MaxOffset ->end ()) {
447
- (*Next.Reg2MaxOffset )[OC.ToReg ] = (*I).second - Offset;
513
+ (*Next.Reg2MaxOffset )[OC.ToReg ] = (*I).second + (- Offset) ;
448
514
FixedOffsetRegJustSet = OC.ToReg ;
449
515
}
450
516
}
0 commit comments