1919#include " llvm/MC/MCInst.h"
2020#include " llvm/Support/Format.h"
2121
22+ #include < limits>
23+
2224#define DEBUG_TYPE " bolt-stackclash"
2325
2426namespace llvm {
@@ -68,6 +70,51 @@ bool addToMaxMap(SmallDenseMap<MCPhysReg, uint64_t, 1> &M, MCPhysReg R,
6870 }
6971}
7072
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+
71118struct State {
72119 // Store the maximum possible offset to which the stack extends
73120 // beyond the furthest probe seen.
@@ -89,7 +136,7 @@ struct State {
89136 // / This is only tracked in Basic Blocks that are known to be reachable
90137 // / from an entry block. For blocks not (yet) known to be reachable from
91138 // / 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;
93140 // FIXME: It seems that conceptually it does not make sense to
94141 // track wheterh the SP value is currently at a fixed offset from
95142 // the value it was at function entry.
@@ -139,12 +186,18 @@ struct State {
139186 SPFixedOffsetFromOrig.reset ();
140187
141188 if (StateIn.Reg2MaxOffset && Reg2MaxOffset) {
142- SmallDenseMap<MCPhysReg, int64_t , 2 > MergedMap;
189+ SmallDenseMap<MCPhysReg, MaxOffsetT , 2 > MergedMap;
143190 for (auto R2MaxOff : *Reg2MaxOffset) {
144191 const MCPhysReg R = R2MaxOff.first ;
145192 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+ }
148201 }
149202 Reg2MaxOffset = MergedMap;
150203 } else if (StateIn.Reg2MaxOffset && !Reg2MaxOffset) {
@@ -266,8 +319,7 @@ bool checkNonConstSPOffsetChange(const BinaryContext &BC, BinaryFunction &BF,
266319 << " ; new MaxOffsetSinceLastProbe: "
267320 << Next->MaxOffsetSinceLastProbe
268321 << " ; new SPFixedOffsetFromOrig: "
269- << Next->SPFixedOffsetFromOrig
270- << " \n " ;
322+ << Next->SPFixedOffsetFromOrig << " \n " ;
271323 });
272324 }
273325 // assert(!OC.IsPreIndexOffsetChange || IsStackAccess);
@@ -276,10 +328,21 @@ bool checkNonConstSPOffsetChange(const BinaryContext &BC, BinaryFunction &BF,
276328 } else if (Cur.Reg2MaxOffset && Cur.Reg2MaxOffset ->contains (OC.FromReg ) &&
277329 OC.OffsetChange ) {
278330 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 ;
283346 }
284347 }
285348 }
@@ -293,12 +356,15 @@ bool checkNonConstSPOffsetChange(const BinaryContext &BC, BinaryFunction &BF,
293356 // and sp, x9, #0xffffffffffffff80
294357 uint64_t BitsToZeroMask = ~Mask;
295358 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 ();
299366 Next->SPFixedOffsetFromOrig = std::nullopt ;
300367 }
301- IsNonConstantSPOffsetChange = false ;
302368 }
303369
304370 return IsNonConstantSPOffsetChange;
@@ -328,7 +394,7 @@ class StackClashDFAnalysis
328394 State getStartingStateAtBB (const BinaryBasicBlock &BB) {
329395 State Next;
330396 if (BB.isEntryPoint ())
331- Next.Reg2MaxOffset = SmallDenseMap<MCPhysReg, int64_t , 2 >();
397+ Next.Reg2MaxOffset = SmallDenseMap<MCPhysReg, MaxOffsetT , 2 >();
332398 return Next;
333399 }
334400
@@ -440,11 +506,11 @@ class StackClashDFAnalysis
440506 int64_t Offset = *OC.OffsetChange ;
441507 if (OC.FromReg == SP) {
442508 (*Next.Reg2MaxOffset )[OC.ToReg ] =
443- *Cur.MaxOffsetSinceLastProbe - Offset;
509+ *Cur.MaxOffsetSinceLastProbe + (- Offset) ;
444510 FixedOffsetRegJustSet = OC.ToReg ;
445511 } else if (auto I = Cur.Reg2MaxOffset ->find (OC.FromReg );
446512 I != Cur.Reg2MaxOffset ->end ()) {
447- (*Next.Reg2MaxOffset )[OC.ToReg ] = (*I).second - Offset;
513+ (*Next.Reg2MaxOffset )[OC.ToReg ] = (*I).second + (- Offset) ;
448514 FixedOffsetRegJustSet = OC.ToReg ;
449515 }
450516 }
0 commit comments