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