xref: /llvm-project/bolt/lib/Passes/StackAllocationAnalysis.cpp (revision c09cd64e5c6dea6e97ef7d6cee5f689df2b408d7)
12f09f445SMaksim Panchenko //===- bolt/Passes/StackAllocationAnalysis.cpp ----------------------------===//
2a34c753fSRafael Auler //
3a34c753fSRafael Auler // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4a34c753fSRafael Auler // See https://llvm.org/LICENSE.txt for license information.
5a34c753fSRafael Auler // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a34c753fSRafael Auler //
7a34c753fSRafael Auler //===----------------------------------------------------------------------===//
8a34c753fSRafael Auler //
92f09f445SMaksim Panchenko // This file implements the StackAllocationAnalysis class.
102f09f445SMaksim Panchenko //
11a34c753fSRafael Auler //===----------------------------------------------------------------------===//
12a34c753fSRafael Auler 
13a34c753fSRafael Auler #include "bolt/Passes/StackAllocationAnalysis.h"
14a34c753fSRafael Auler #include "bolt/Passes/StackPointerTracking.h"
15a34c753fSRafael Auler #include "llvm/Support/Debug.h"
16a34c753fSRafael Auler 
17a34c753fSRafael Auler #define DEBUG_TYPE "saa"
18a34c753fSRafael Auler 
19a34c753fSRafael Auler namespace llvm {
20a34c753fSRafael Auler namespace bolt {
21a34c753fSRafael Auler 
preflight()22a34c753fSRafael Auler void StackAllocationAnalysis::preflight() {
23a34c753fSRafael Auler   LLVM_DEBUG(dbgs() << "Starting StackAllocationAnalysis on \""
24a34c753fSRafael Auler                     << Func.getPrintName() << "\"\n");
25a34c753fSRafael Auler 
26a34c753fSRafael Auler   for (BinaryBasicBlock &BB : this->Func) {
27a34c753fSRafael Auler     for (MCInst &Inst : BB) {
28a34c753fSRafael Auler       MCPhysReg From, To;
2940c2e0faSMaksim Panchenko       if (!BC.MIB->isPush(Inst) &&
3040c2e0faSMaksim Panchenko           (!BC.MIB->isRegToRegMove(Inst, From, To) ||
31a34c753fSRafael Auler            To != BC.MIB->getStackPointer() ||
32a34c753fSRafael Auler            From != BC.MIB->getFramePointer()) &&
33a34c753fSRafael Auler           !BC.MII->get(Inst.getOpcode())
34a34c753fSRafael Auler                .hasDefOfPhysReg(Inst, BC.MIB->getStackPointer(), *BC.MRI))
35a34c753fSRafael Auler         continue;
36a34c753fSRafael Auler       this->Expressions.push_back(&Inst);
37a34c753fSRafael Auler       this->ExprToIdx[&Inst] = this->NumInstrs++;
38a34c753fSRafael Auler     }
39a34c753fSRafael Auler   }
40a34c753fSRafael Auler }
41a34c753fSRafael Auler 
42a34c753fSRafael Auler BitVector
getStartingStateAtBB(const BinaryBasicBlock & BB)43a34c753fSRafael Auler StackAllocationAnalysis::getStartingStateAtBB(const BinaryBasicBlock &BB) {
44a34c753fSRafael Auler   return BitVector(this->NumInstrs, false);
45a34c753fSRafael Auler }
46a34c753fSRafael Auler 
47a34c753fSRafael Auler BitVector
getStartingStateAtPoint(const MCInst & Point)48a34c753fSRafael Auler StackAllocationAnalysis::getStartingStateAtPoint(const MCInst &Point) {
49a34c753fSRafael Auler   return BitVector(this->NumInstrs, false);
50a34c753fSRafael Auler }
51a34c753fSRafael Auler 
doConfluence(BitVector & StateOut,const BitVector & StateIn)52a34c753fSRafael Auler void StackAllocationAnalysis::doConfluence(BitVector &StateOut,
53a34c753fSRafael Auler                                            const BitVector &StateIn) {
54a34c753fSRafael Auler   StateOut |= StateIn;
55a34c753fSRafael Auler }
56a34c753fSRafael Auler 
doKill(const MCInst & Point,const BitVector & StateIn,int DeallocSize)57a34c753fSRafael Auler BitVector StackAllocationAnalysis::doKill(const MCInst &Point,
58a34c753fSRafael Auler                                           const BitVector &StateIn,
59a34c753fSRafael Auler                                           int DeallocSize) {
60a34c753fSRafael Auler   int64_t SPOffset = SPT.getStateAt(Point)->first;
61a34c753fSRafael Auler   BitVector Next = StateIn;
62a34c753fSRafael Auler   if (SPOffset == SPT.SUPERPOSITION || SPOffset == SPT.EMPTY)
63a34c753fSRafael Auler     return Next;
64a34c753fSRafael Auler   for (auto I = this->expr_begin(Next), E = this->expr_end(); I != E; ++I) {
65a34c753fSRafael Auler     const MCInst *Instr = *I;
66a34c753fSRafael Auler     int64_t InstrOffset = SPT.getStateAt(*Instr)->first;
67a34c753fSRafael Auler     if (InstrOffset == SPT.SUPERPOSITION || InstrOffset == SPT.EMPTY)
68a34c753fSRafael Auler       continue;
69a34c753fSRafael Auler     if (InstrOffset < SPOffset) {
70a34c753fSRafael Auler       Next.reset(I.getBitVectorIndex());
71a34c753fSRafael Auler       LLVM_DEBUG({
72a34c753fSRafael Auler         dbgs() << "SAA FYI: Killed: ";
73a34c753fSRafael Auler         Instr->dump();
74a34c753fSRafael Auler         dbgs() << "by: ";
75a34c753fSRafael Auler         Point.dump();
76a34c753fSRafael Auler         dbgs() << "  (more info: Killed instr offset = " << InstrOffset
77a34c753fSRafael Auler                << ". SPOffset = " << SPOffset
78a34c753fSRafael Auler                << "; DeallocSize= " << DeallocSize << "\n";
79a34c753fSRafael Auler       });
80a34c753fSRafael Auler     }
81a34c753fSRafael Auler   }
82a34c753fSRafael Auler   return Next;
83a34c753fSRafael Auler }
84a34c753fSRafael Auler 
doConfluenceWithLP(BitVector & StateOut,const BitVector & StateIn,const MCInst & Invoke)85a34c753fSRafael Auler void StackAllocationAnalysis::doConfluenceWithLP(BitVector &StateOut,
86a34c753fSRafael Auler                                                  const BitVector &StateIn,
87a34c753fSRafael Auler                                                  const MCInst &Invoke) {
88a34c753fSRafael Auler   BitVector NewIn = StateIn;
89a34c753fSRafael Auler   const int64_t GnuArgsSize = BC.MIB->getGnuArgsSize(Invoke);
90a34c753fSRafael Auler   if (GnuArgsSize >= 0)
91a34c753fSRafael Auler     NewIn = doKill(Invoke, NewIn, GnuArgsSize);
92a34c753fSRafael Auler   StateOut |= NewIn;
93a34c753fSRafael Auler }
94a34c753fSRafael Auler 
computeNext(const MCInst & Point,const BitVector & Cur)95a34c753fSRafael Auler BitVector StackAllocationAnalysis::computeNext(const MCInst &Point,
96a34c753fSRafael Auler                                                const BitVector &Cur) {
97a34c753fSRafael Auler   const auto &MIB = BC.MIB;
98a34c753fSRafael Auler   BitVector Next = Cur;
99a34c753fSRafael Auler   if (int Sz = MIB->getPopSize(Point)) {
100a34c753fSRafael Auler     Next = doKill(Point, Next, Sz);
101a34c753fSRafael Auler     return Next;
102a34c753fSRafael Auler   }
103a34c753fSRafael Auler   if (MIB->isPush(Point)) {
104a34c753fSRafael Auler     Next.set(this->ExprToIdx[&Point]);
105a34c753fSRafael Auler     return Next;
106a34c753fSRafael Auler   }
107a34c753fSRafael Auler 
108a34c753fSRafael Auler   MCPhysReg From, To;
109a34c753fSRafael Auler   int64_t SPOffset, FPOffset;
110a34c753fSRafael Auler   std::tie(SPOffset, FPOffset) = *SPT.getStateBefore(Point);
111a34c753fSRafael Auler   if (MIB->isRegToRegMove(Point, From, To) && To == MIB->getStackPointer() &&
112a34c753fSRafael Auler       From == MIB->getFramePointer()) {
113a34c753fSRafael Auler     if (MIB->isLeave(Point))
114a34c753fSRafael Auler       FPOffset += 8;
115a34c753fSRafael Auler     if (SPOffset < FPOffset) {
116a34c753fSRafael Auler       Next = doKill(Point, Next, FPOffset - SPOffset);
117a34c753fSRafael Auler       return Next;
118a34c753fSRafael Auler     }
119a34c753fSRafael Auler     if (SPOffset > FPOffset) {
120a34c753fSRafael Auler       Next.set(this->ExprToIdx[&Point]);
121a34c753fSRafael Auler       return Next;
122a34c753fSRafael Auler     }
123a34c753fSRafael Auler   }
124a34c753fSRafael Auler   if (BC.MII->get(Point.getOpcode())
125a34c753fSRafael Auler           .hasDefOfPhysReg(Point, MIB->getStackPointer(), *BC.MRI)) {
126a34c753fSRafael Auler     std::pair<MCPhysReg, int64_t> SP;
127a34c753fSRafael Auler     if (SPOffset != SPT.EMPTY && SPOffset != SPT.SUPERPOSITION)
128a34c753fSRafael Auler       SP = std::make_pair(MIB->getStackPointer(), SPOffset);
129a34c753fSRafael Auler     else
130a34c753fSRafael Auler       SP = std::make_pair(0, 0);
131a34c753fSRafael Auler     std::pair<MCPhysReg, int64_t> FP;
132a34c753fSRafael Auler     if (FPOffset != SPT.EMPTY && FPOffset != SPT.SUPERPOSITION)
133a34c753fSRafael Auler       FP = std::make_pair(MIB->getFramePointer(), FPOffset);
134a34c753fSRafael Auler     else
135a34c753fSRafael Auler       FP = std::make_pair(0, 0);
136a34c753fSRafael Auler     int64_t Output;
137*c09cd64eSRafael Auler     if (!MIB->evaluateStackOffsetExpr(Point, Output, SP, FP))
138a34c753fSRafael Auler       return Next;
139a34c753fSRafael Auler 
140a34c753fSRafael Auler     if (SPOffset < Output) {
141a34c753fSRafael Auler       Next = doKill(Point, Next, Output - SPOffset);
142a34c753fSRafael Auler       return Next;
143a34c753fSRafael Auler     }
144a34c753fSRafael Auler     if (SPOffset > Output) {
145a34c753fSRafael Auler       Next.set(this->ExprToIdx[&Point]);
146a34c753fSRafael Auler       return Next;
147a34c753fSRafael Auler     }
148a34c753fSRafael Auler   }
149a34c753fSRafael Auler   return Next;
150a34c753fSRafael Auler }
151a34c753fSRafael Auler 
152a34c753fSRafael Auler } // end namespace bolt
153a34c753fSRafael Auler } // end namespace llvm
154