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

source code of bolt/lib/Passes/StackReachingUses.cpp