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