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