forked from OSchip/llvm-project
134 lines
4.4 KiB
C++
134 lines
4.4 KiB
C++
//===- bolt/Passes/StackAvailableExpressions.cpp --------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements the StackAvailableExpressions class.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "bolt/Passes/StackAvailableExpressions.h"
|
|
#include "bolt/Passes/FrameAnalysis.h"
|
|
#include "bolt/Passes/RegAnalysis.h"
|
|
#include "llvm/MC/MCRegisterInfo.h"
|
|
|
|
#define DEBUG_TYPE "sae"
|
|
|
|
namespace llvm {
|
|
namespace bolt {
|
|
|
|
StackAvailableExpressions::StackAvailableExpressions(const RegAnalysis &RA,
|
|
const FrameAnalysis &FA,
|
|
BinaryFunction &BF)
|
|
: InstrsDataflowAnalysis(BF), RA(RA), FA(FA) {}
|
|
|
|
void StackAvailableExpressions::preflight() {
|
|
LLVM_DEBUG(dbgs() << "Starting StackAvailableExpressions on \""
|
|
<< Func.getPrintName() << "\"\n");
|
|
|
|
// Populate our universe of tracked expressions. We are interested in
|
|
// tracking available stores to frame position at any given point of the
|
|
// program.
|
|
for (BinaryBasicBlock &BB : Func) {
|
|
for (MCInst &Inst : BB) {
|
|
ErrorOr<const FrameIndexEntry &> FIE = FA.getFIEFor(Inst);
|
|
if (!FIE)
|
|
continue;
|
|
if (FIE->IsStore == true && FIE->IsSimple == true) {
|
|
Expressions.push_back(&Inst);
|
|
ExprToIdx[&Inst] = NumInstrs++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
BitVector
|
|
StackAvailableExpressions::getStartingStateAtBB(const BinaryBasicBlock &BB) {
|
|
// Entry points start with empty set
|
|
// All others start with the full set.
|
|
if (BB.pred_size() == 0 && BB.throw_size() == 0)
|
|
return BitVector(NumInstrs, false);
|
|
return BitVector(NumInstrs, true);
|
|
}
|
|
|
|
BitVector
|
|
StackAvailableExpressions::getStartingStateAtPoint(const MCInst &Point) {
|
|
return BitVector(NumInstrs, true);
|
|
}
|
|
|
|
void StackAvailableExpressions::doConfluence(BitVector &StateOut,
|
|
const BitVector &StateIn) {
|
|
StateOut &= StateIn;
|
|
}
|
|
|
|
namespace {
|
|
|
|
bool isLoadRedundant(const FrameIndexEntry &LoadFIE,
|
|
const FrameIndexEntry &StoreFIE) {
|
|
if (LoadFIE.IsLoad == false || LoadFIE.IsSimple == false)
|
|
return false;
|
|
if (LoadFIE.StackOffset == StoreFIE.StackOffset &&
|
|
LoadFIE.Size == StoreFIE.Size)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool StackAvailableExpressions::doesXKillsY(const MCInst *X, const MCInst *Y) {
|
|
// if both are stores, and both store to the same stack location, return
|
|
// true
|
|
ErrorOr<const FrameIndexEntry &> FIEX = FA.getFIEFor(*X);
|
|
ErrorOr<const FrameIndexEntry &> FIEY = FA.getFIEFor(*Y);
|
|
if (FIEX && FIEY) {
|
|
if (isLoadRedundant(*FIEX, *FIEY))
|
|
return false;
|
|
if (FIEX->IsStore == true && FIEY->IsStore == true &&
|
|
FIEX->StackOffset + FIEX->Size > FIEY->StackOffset &&
|
|
FIEX->StackOffset < FIEY->StackOffset + FIEY->Size)
|
|
return true;
|
|
}
|
|
// getClobberedRegs for X and Y. If they intersect, return true
|
|
BitVector XClobbers = BitVector(BC.MRI->getNumRegs(), false);
|
|
BitVector YClobbers = BitVector(BC.MRI->getNumRegs(), false);
|
|
RA.getInstClobberList(*X, XClobbers);
|
|
// If Y is a store to stack, its clobber list is its source reg. This is
|
|
// different than the rest because we want to check if the store source
|
|
// reaches its corresponding load untouched.
|
|
if (FIEY && FIEY->IsStore == true && FIEY->IsStoreFromReg)
|
|
YClobbers.set(FIEY->RegOrImm);
|
|
else
|
|
RA.getInstClobberList(*Y, YClobbers);
|
|
|
|
XClobbers &= YClobbers;
|
|
return XClobbers.any();
|
|
}
|
|
|
|
BitVector StackAvailableExpressions::computeNext(const MCInst &Point,
|
|
const BitVector &Cur) {
|
|
BitVector Next = Cur;
|
|
// Kill
|
|
for (auto I = expr_begin(Next), E = expr_end(); I != E; ++I) {
|
|
assert(*I != nullptr && "Lost pointers");
|
|
LLVM_DEBUG(dbgs() << "\t\t\tDoes it kill ");
|
|
LLVM_DEBUG((*I)->dump());
|
|
if (doesXKillsY(&Point, *I)) {
|
|
LLVM_DEBUG(dbgs() << "\t\t\t\tKilling ");
|
|
LLVM_DEBUG((*I)->dump());
|
|
Next.reset(I.getBitVectorIndex());
|
|
}
|
|
}
|
|
// Gen
|
|
if (ErrorOr<const FrameIndexEntry &> FIE = FA.getFIEFor(Point)) {
|
|
if (FIE->IsStore == true && FIE->IsSimple == true)
|
|
Next.set(ExprToIdx[&Point]);
|
|
}
|
|
return Next;
|
|
}
|
|
|
|
} // namespace bolt
|
|
} // namespace llvm
|