xref: /llvm-project/bolt/lib/Passes/StackReachingUses.cpp (revision 4c106cfdf7cf7eec861ad3983a3dd9a9e8f3a8ae)
12f09f445SMaksim Panchenko //===- bolt/Passes/StackReachingUses.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 StackReachingUses class.
102f09f445SMaksim Panchenko //
11a34c753fSRafael Auler //===----------------------------------------------------------------------===//
122f09f445SMaksim Panchenko 
13a34c753fSRafael Auler #include "bolt/Passes/StackReachingUses.h"
14a34c753fSRafael Auler #include "bolt/Passes/FrameAnalysis.h"
15a34c753fSRafael Auler 
16a34c753fSRafael Auler #define DEBUG_TYPE "sru"
17a34c753fSRafael Auler 
18a34c753fSRafael Auler namespace llvm {
19a34c753fSRafael Auler namespace bolt {
20a34c753fSRafael Auler 
isLoadedInDifferentReg(const FrameIndexEntry & StoreFIE,ExprIterator Candidates) const21a34c753fSRafael Auler bool StackReachingUses::isLoadedInDifferentReg(const FrameIndexEntry &StoreFIE,
22a34c753fSRafael Auler                                                ExprIterator Candidates) const {
23a34c753fSRafael Auler   for (auto I = Candidates; I != expr_end(); ++I) {
24a34c753fSRafael Auler     const MCInst *ReachingInst = *I;
25a34c753fSRafael Auler     if (ErrorOr<const FrameIndexEntry &> FIEY = FA.getFIEFor(*ReachingInst)) {
26a34c753fSRafael Auler       assert(FIEY->IsLoad == 1);
27a34c753fSRafael Auler       if (StoreFIE.StackOffset + StoreFIE.Size > FIEY->StackOffset &&
28a34c753fSRafael Auler           StoreFIE.StackOffset < FIEY->StackOffset + FIEY->Size &&
29*f92ab6afSAmir Ayupov           StoreFIE.RegOrImm != FIEY->RegOrImm)
30a34c753fSRafael Auler         return true;
31a34c753fSRafael Auler     }
32a34c753fSRafael Auler   }
33a34c753fSRafael Auler   return false;
34a34c753fSRafael Auler }
35a34c753fSRafael Auler 
isStoreUsed(const FrameIndexEntry & StoreFIE,ExprIterator Candidates,bool IncludeLocalAccesses) const36a34c753fSRafael Auler bool StackReachingUses::isStoreUsed(const FrameIndexEntry &StoreFIE,
37a34c753fSRafael Auler                                     ExprIterator Candidates,
38a34c753fSRafael Auler                                     bool IncludeLocalAccesses) const {
39a34c753fSRafael Auler   for (auto I = Candidates; I != expr_end(); ++I) {
40a34c753fSRafael Auler     const MCInst *ReachingInst = *I;
41a34c753fSRafael Auler     if (IncludeLocalAccesses) {
42a34c753fSRafael Auler       if (ErrorOr<const FrameIndexEntry &> FIEY = FA.getFIEFor(*ReachingInst)) {
43a34c753fSRafael Auler         assert(FIEY->IsLoad == 1);
44a34c753fSRafael Auler         if (StoreFIE.StackOffset + StoreFIE.Size > FIEY->StackOffset &&
45*f92ab6afSAmir Ayupov             StoreFIE.StackOffset < FIEY->StackOffset + FIEY->Size)
46a34c753fSRafael Auler           return true;
47a34c753fSRafael Auler       }
48a34c753fSRafael Auler     }
49a34c753fSRafael Auler     ErrorOr<const ArgAccesses &> Args = FA.getArgAccessesFor(*ReachingInst);
50a34c753fSRafael Auler     if (!Args)
51a34c753fSRafael Auler       continue;
52*f92ab6afSAmir Ayupov     if (Args->AssumeEverything)
53a34c753fSRafael Auler       return true;
54*f92ab6afSAmir Ayupov 
55*f92ab6afSAmir Ayupov     for (ArgInStackAccess FIEY : Args->Set)
56a34c753fSRafael Auler       if (StoreFIE.StackOffset + StoreFIE.Size > FIEY.StackOffset &&
57*f92ab6afSAmir Ayupov           StoreFIE.StackOffset < FIEY.StackOffset + FIEY.Size)
58a34c753fSRafael Auler         return true;
59a34c753fSRafael Auler   }
60a34c753fSRafael Auler   return false;
61a34c753fSRafael Auler }
62a34c753fSRafael Auler 
preflight()63a34c753fSRafael Auler void StackReachingUses::preflight() {
64a34c753fSRafael Auler   LLVM_DEBUG(dbgs() << "Starting StackReachingUses on \"" << Func.getPrintName()
65a34c753fSRafael Auler                     << "\"\n");
66a34c753fSRafael Auler 
67a34c753fSRafael Auler   // Populate our universe of tracked expressions. We are interested in
68a34c753fSRafael Auler   // tracking reaching loads from frame position at any given point of the
69a34c753fSRafael Auler   // program.
70a34c753fSRafael Auler   for (BinaryBasicBlock &BB : Func) {
71a34c753fSRafael Auler     for (MCInst &Inst : BB) {
72a34c753fSRafael Auler       if (ErrorOr<const FrameIndexEntry &> FIE = FA.getFIEFor(Inst)) {
73a34c753fSRafael Auler         if (FIE->IsLoad == true) {
74a34c753fSRafael Auler           Expressions.push_back(&Inst);
75a34c753fSRafael Auler           ExprToIdx[&Inst] = NumInstrs++;
76a34c753fSRafael Auler           continue;
77a34c753fSRafael Auler         }
78a34c753fSRafael Auler       }
79a34c753fSRafael Auler       ErrorOr<const ArgAccesses &> AA = FA.getArgAccessesFor(Inst);
80a34c753fSRafael Auler       if (AA && (!AA->Set.empty() || AA->AssumeEverything)) {
81a34c753fSRafael Auler         Expressions.push_back(&Inst);
82a34c753fSRafael Auler         ExprToIdx[&Inst] = NumInstrs++;
83a34c753fSRafael Auler       }
84a34c753fSRafael Auler     }
85a34c753fSRafael Auler   }
86a34c753fSRafael Auler }
87a34c753fSRafael Auler 
doesXKillsY(const MCInst * X,const MCInst * Y)88a34c753fSRafael Auler bool StackReachingUses::doesXKillsY(const MCInst *X, const MCInst *Y) {
89a34c753fSRafael Auler   // if X is a store to the same stack location and the bytes fetched is a
90a34c753fSRafael Auler   // superset of those bytes affected by the load in Y, return true
91a34c753fSRafael Auler   ErrorOr<const FrameIndexEntry &> FIEX = FA.getFIEFor(*X);
92a34c753fSRafael Auler   ErrorOr<const FrameIndexEntry &> FIEY = FA.getFIEFor(*Y);
93a34c753fSRafael Auler   if (FIEX && FIEY) {
94a34c753fSRafael Auler     if (FIEX->IsSimple == true && FIEY->IsSimple == true &&
95a34c753fSRafael Auler         FIEX->IsStore == true && FIEY->IsLoad == true &&
96a34c753fSRafael Auler         FIEX->StackOffset <= FIEY->StackOffset &&
97a34c753fSRafael Auler         FIEX->StackOffset + FIEX->Size >= FIEY->StackOffset + FIEY->Size)
98a34c753fSRafael Auler       return true;
99a34c753fSRafael Auler   }
100a34c753fSRafael Auler   return false;
101a34c753fSRafael Auler }
102a34c753fSRafael Auler 
computeNext(const MCInst & Point,const BitVector & Cur)103a34c753fSRafael Auler BitVector StackReachingUses::computeNext(const MCInst &Point,
104a34c753fSRafael Auler                                          const BitVector &Cur) {
105a34c753fSRafael Auler   BitVector Next = Cur;
106a34c753fSRafael Auler   // Kill
107a34c753fSRafael Auler   for (auto I = expr_begin(Next), E = expr_end(); I != E; ++I) {
108a34c753fSRafael Auler     assert(*I != nullptr && "Lost pointers");
109a34c753fSRafael Auler     if (doesXKillsY(&Point, *I)) {
110a34c753fSRafael Auler       LLVM_DEBUG(dbgs() << "\t\t\tKilling ");
111a34c753fSRafael Auler       LLVM_DEBUG((*I)->dump());
112a34c753fSRafael Auler       Next.reset(I.getBitVectorIndex());
113a34c753fSRafael Auler     }
114a34c753fSRafael Auler   };
115a34c753fSRafael Auler   // Gen
116a34c753fSRafael Auler   if (ErrorOr<const FrameIndexEntry &> FIE = FA.getFIEFor(Point)) {
117a34c753fSRafael Auler     if (FIE->IsLoad == true)
118a34c753fSRafael Auler       Next.set(ExprToIdx[&Point]);
119a34c753fSRafael Auler   }
120a34c753fSRafael Auler   ErrorOr<const ArgAccesses &> AA = FA.getArgAccessesFor(Point);
121a34c753fSRafael Auler   if (AA && (!AA->Set.empty() || AA->AssumeEverything))
122a34c753fSRafael Auler     Next.set(ExprToIdx[&Point]);
123a34c753fSRafael Auler   return Next;
124a34c753fSRafael Auler }
125a34c753fSRafael Auler 
126a34c753fSRafael Auler } // namespace bolt
127a34c753fSRafael Auler } // namespace llvm
128