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