xref: /llvm-project/bolt/lib/Passes/StackAvailableExpressions.cpp (revision 2f09f445b2d6b3ef197aecd8d1e06d08140380f3)
1*2f09f445SMaksim Panchenko //===- bolt/Passes/StackAvailableExpressions.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 //
9*2f09f445SMaksim Panchenko // This file implements the StackAvailableExpressions class.
10*2f09f445SMaksim Panchenko //
11a34c753fSRafael Auler //===----------------------------------------------------------------------===//
12a34c753fSRafael Auler 
13a34c753fSRafael Auler #include "bolt/Passes/StackAvailableExpressions.h"
14a34c753fSRafael Auler #include "bolt/Passes/FrameAnalysis.h"
15a34c753fSRafael Auler #include "bolt/Passes/RegAnalysis.h"
16a34c753fSRafael Auler 
17a34c753fSRafael Auler #define DEBUG_TYPE "sae"
18a34c753fSRafael Auler 
19a34c753fSRafael Auler namespace llvm {
20a34c753fSRafael Auler namespace bolt {
21a34c753fSRafael Auler 
22a34c753fSRafael Auler StackAvailableExpressions::StackAvailableExpressions(const RegAnalysis &RA,
23a34c753fSRafael Auler                                                      const FrameAnalysis &FA,
24a34c753fSRafael Auler                                                      BinaryFunction &BF)
2560b09997SMaksim Panchenko     : InstrsDataflowAnalysis(BF), RA(RA), FA(FA) {}
26a34c753fSRafael Auler 
27a34c753fSRafael Auler void StackAvailableExpressions::preflight() {
28a34c753fSRafael Auler   LLVM_DEBUG(dbgs() << "Starting StackAvailableExpressions on \""
29a34c753fSRafael Auler                     << Func.getPrintName() << "\"\n");
30a34c753fSRafael Auler 
31a34c753fSRafael Auler   // Populate our universe of tracked expressions. We are interested in
32a34c753fSRafael Auler   // tracking available stores to frame position at any given point of the
33a34c753fSRafael Auler   // program.
34a34c753fSRafael Auler   for (BinaryBasicBlock &BB : Func) {
35a34c753fSRafael Auler     for (MCInst &Inst : BB) {
36a34c753fSRafael Auler       ErrorOr<const FrameIndexEntry &> FIE = FA.getFIEFor(Inst);
37a34c753fSRafael Auler       if (!FIE)
38a34c753fSRafael Auler         continue;
39a34c753fSRafael Auler       if (FIE->IsStore == true && FIE->IsSimple == true) {
40a34c753fSRafael Auler         Expressions.push_back(&Inst);
41a34c753fSRafael Auler         ExprToIdx[&Inst] = NumInstrs++;
42a34c753fSRafael Auler       }
43a34c753fSRafael Auler     }
44a34c753fSRafael Auler   }
45a34c753fSRafael Auler }
46a34c753fSRafael Auler 
47a34c753fSRafael Auler BitVector
48a34c753fSRafael Auler StackAvailableExpressions::getStartingStateAtBB(const BinaryBasicBlock &BB) {
49a34c753fSRafael Auler   // Entry points start with empty set
50a34c753fSRafael Auler   // All others start with the full set.
51a34c753fSRafael Auler   if (BB.pred_size() == 0 && BB.throw_size() == 0)
52a34c753fSRafael Auler     return BitVector(NumInstrs, false);
53a34c753fSRafael Auler   return BitVector(NumInstrs, true);
54a34c753fSRafael Auler }
55a34c753fSRafael Auler 
56a34c753fSRafael Auler BitVector
57a34c753fSRafael Auler StackAvailableExpressions::getStartingStateAtPoint(const MCInst &Point) {
58a34c753fSRafael Auler   return BitVector(NumInstrs, true);
59a34c753fSRafael Auler }
60a34c753fSRafael Auler 
61a34c753fSRafael Auler void StackAvailableExpressions::doConfluence(BitVector &StateOut,
62a34c753fSRafael Auler                                              const BitVector &StateIn) {
63a34c753fSRafael Auler   StateOut &= StateIn;
64a34c753fSRafael Auler }
65a34c753fSRafael Auler 
66a34c753fSRafael Auler namespace {
67a34c753fSRafael Auler 
68a34c753fSRafael Auler bool isLoadRedundant(const FrameIndexEntry &LoadFIE,
69a34c753fSRafael Auler                      const FrameIndexEntry &StoreFIE) {
70a34c753fSRafael Auler   if (LoadFIE.IsLoad == false || LoadFIE.IsSimple == false) {
71a34c753fSRafael Auler     return false;
72a34c753fSRafael Auler   }
73a34c753fSRafael Auler   if (LoadFIE.StackOffset == StoreFIE.StackOffset &&
74a34c753fSRafael Auler       LoadFIE.Size == StoreFIE.Size) {
75a34c753fSRafael Auler     return true;
76a34c753fSRafael Auler   }
77a34c753fSRafael Auler 
78a34c753fSRafael Auler   return false;
79a34c753fSRafael Auler }
80a34c753fSRafael Auler }
81a34c753fSRafael Auler 
82a34c753fSRafael Auler bool StackAvailableExpressions::doesXKillsY(const MCInst *X, const MCInst *Y) {
83a34c753fSRafael Auler   // if both are stores, and both store to the same stack location, return
84a34c753fSRafael Auler   // true
85a34c753fSRafael Auler   ErrorOr<const FrameIndexEntry &> FIEX = FA.getFIEFor(*X);
86a34c753fSRafael Auler   ErrorOr<const FrameIndexEntry &> FIEY = FA.getFIEFor(*Y);
87a34c753fSRafael Auler   if (FIEX && FIEY) {
88a34c753fSRafael Auler     if (isLoadRedundant(*FIEX, *FIEY))
89a34c753fSRafael Auler       return false;
90a34c753fSRafael Auler     if (FIEX->IsStore == true && FIEY->IsStore == true &&
91a34c753fSRafael Auler         FIEX->StackOffset + FIEX->Size > FIEY->StackOffset &&
92a34c753fSRafael Auler         FIEX->StackOffset < FIEY->StackOffset + FIEY->Size)
93a34c753fSRafael Auler       return true;
94a34c753fSRafael Auler   }
95a34c753fSRafael Auler   // getClobberedRegs for X and Y. If they intersect, return true
96a34c753fSRafael Auler   BitVector XClobbers = BitVector(BC.MRI->getNumRegs(), false);
97a34c753fSRafael Auler   BitVector YClobbers = BitVector(BC.MRI->getNumRegs(), false);
98a34c753fSRafael Auler   RA.getInstClobberList(*X, XClobbers);
99a34c753fSRafael Auler   // If Y is a store to stack, its clobber list is its source reg. This is
100a34c753fSRafael Auler   // different than the rest because we want to check if the store source
101a34c753fSRafael Auler   // reaches its corresponding load untouched.
102a34c753fSRafael Auler   if (FIEY && FIEY->IsStore == true && FIEY->IsStoreFromReg) {
103a34c753fSRafael Auler     YClobbers.set(FIEY->RegOrImm);
104a34c753fSRafael Auler   } else {
105a34c753fSRafael Auler     RA.getInstClobberList(*Y, YClobbers);
106a34c753fSRafael Auler   }
107a34c753fSRafael Auler   XClobbers &= YClobbers;
108a34c753fSRafael Auler   return XClobbers.any();
109a34c753fSRafael Auler }
110a34c753fSRafael Auler 
111a34c753fSRafael Auler BitVector StackAvailableExpressions::computeNext(const MCInst &Point,
112a34c753fSRafael Auler                                                  const BitVector &Cur) {
113a34c753fSRafael Auler   BitVector Next = Cur;
114a34c753fSRafael Auler   // Kill
115a34c753fSRafael Auler   for (auto I = expr_begin(Next), E = expr_end(); I != E; ++I) {
116a34c753fSRafael Auler     assert(*I != nullptr && "Lost pointers");
117a34c753fSRafael Auler     LLVM_DEBUG(dbgs() << "\t\t\tDoes it kill ");
118a34c753fSRafael Auler     LLVM_DEBUG((*I)->dump());
119a34c753fSRafael Auler     if (doesXKillsY(&Point, *I)) {
120a34c753fSRafael Auler       LLVM_DEBUG(dbgs() << "\t\t\t\tKilling ");
121a34c753fSRafael Auler       LLVM_DEBUG((*I)->dump());
122a34c753fSRafael Auler       Next.reset(I.getBitVectorIndex());
123a34c753fSRafael Auler     }
124a34c753fSRafael Auler   }
125a34c753fSRafael Auler   // Gen
126a34c753fSRafael Auler   if (ErrorOr<const FrameIndexEntry &> FIE = FA.getFIEFor(Point)) {
127a34c753fSRafael Auler     if (FIE->IsStore == true && FIE->IsSimple == true)
128a34c753fSRafael Auler       Next.set(ExprToIdx[&Point]);
129a34c753fSRafael Auler   }
130a34c753fSRafael Auler   return Next;
131a34c753fSRafael Auler }
132a34c753fSRafael Auler 
133a34c753fSRafael Auler } // namespace bolt
134a34c753fSRafael Auler } // namespace llvm
135