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