2021-12-21 10:21:41 -08:00
|
|
|
//===- bolt/Passes/StackAllocationAnalysis.cpp ----------------------------===//
|
2017-05-01 16:52:54 -07:00
|
|
|
//
|
2021-03-15 18:04:18 -07:00
|
|
|
// 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
|
2017-05-01 16:52:54 -07:00
|
|
|
//
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
//
|
2021-12-21 10:21:41 -08:00
|
|
|
// This file implements the StackAllocationAnalysis class.
|
|
|
|
|
//
|
2017-05-01 16:52:54 -07:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
2021-10-08 11:47:10 -07:00
|
|
|
#include "bolt/Passes/StackAllocationAnalysis.h"
|
|
|
|
|
#include "bolt/Passes/StackPointerTracking.h"
|
2017-05-01 16:52:54 -07:00
|
|
|
#include "llvm/Support/Debug.h"
|
|
|
|
|
|
|
|
|
|
#define DEBUG_TYPE "saa"
|
|
|
|
|
|
|
|
|
|
namespace llvm {
|
|
|
|
|
namespace bolt {
|
|
|
|
|
|
|
|
|
|
void StackAllocationAnalysis::preflight() {
|
2020-12-01 16:29:39 -08:00
|
|
|
LLVM_DEBUG(dbgs() << "Starting StackAllocationAnalysis on \""
|
|
|
|
|
<< Func.getPrintName() << "\"\n");
|
2017-05-01 16:52:54 -07:00
|
|
|
|
2021-04-08 00:19:26 -07:00
|
|
|
for (BinaryBasicBlock &BB : this->Func) {
|
|
|
|
|
for (MCInst &Inst : BB) {
|
2017-05-01 16:52:54 -07:00
|
|
|
MCPhysReg From, To;
|
2021-12-14 16:52:51 -08:00
|
|
|
if (!BC.MIB->isPush(Inst) &&
|
|
|
|
|
(!BC.MIB->isRegToRegMove(Inst, From, To) ||
|
|
|
|
|
To != BC.MIB->getStackPointer() ||
|
|
|
|
|
From != BC.MIB->getFramePointer()) &&
|
2017-05-01 16:52:54 -07:00
|
|
|
!BC.MII->get(Inst.getOpcode())
|
2018-03-09 09:45:13 -08:00
|
|
|
.hasDefOfPhysReg(Inst, BC.MIB->getStackPointer(), *BC.MRI))
|
2017-05-01 16:52:54 -07:00
|
|
|
continue;
|
|
|
|
|
this->Expressions.push_back(&Inst);
|
|
|
|
|
this->ExprToIdx[&Inst] = this->NumInstrs++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BitVector
|
|
|
|
|
StackAllocationAnalysis::getStartingStateAtBB(const BinaryBasicBlock &BB) {
|
|
|
|
|
return BitVector(this->NumInstrs, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BitVector
|
|
|
|
|
StackAllocationAnalysis::getStartingStateAtPoint(const MCInst &Point) {
|
|
|
|
|
return BitVector(this->NumInstrs, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void StackAllocationAnalysis::doConfluence(BitVector &StateOut,
|
|
|
|
|
const BitVector &StateIn) {
|
|
|
|
|
StateOut |= StateIn;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BitVector StackAllocationAnalysis::doKill(const MCInst &Point,
|
|
|
|
|
const BitVector &StateIn,
|
|
|
|
|
int DeallocSize) {
|
|
|
|
|
int64_t SPOffset = SPT.getStateAt(Point)->first;
|
|
|
|
|
BitVector Next = StateIn;
|
|
|
|
|
if (SPOffset == SPT.SUPERPOSITION || SPOffset == SPT.EMPTY)
|
|
|
|
|
return Next;
|
|
|
|
|
for (auto I = this->expr_begin(Next), E = this->expr_end(); I != E; ++I) {
|
|
|
|
|
const MCInst *Instr = *I;
|
|
|
|
|
int64_t InstrOffset = SPT.getStateAt(*Instr)->first;
|
|
|
|
|
if (InstrOffset == SPT.SUPERPOSITION || InstrOffset == SPT.EMPTY)
|
|
|
|
|
continue;
|
|
|
|
|
if (InstrOffset < SPOffset) {
|
|
|
|
|
Next.reset(I.getBitVectorIndex());
|
2020-12-01 16:29:39 -08:00
|
|
|
LLVM_DEBUG({
|
2017-05-01 16:52:54 -07:00
|
|
|
dbgs() << "SAA FYI: Killed: ";
|
|
|
|
|
Instr->dump();
|
|
|
|
|
dbgs() << "by: ";
|
|
|
|
|
Point.dump();
|
|
|
|
|
dbgs() << " (more info: Killed instr offset = " << InstrOffset
|
|
|
|
|
<< ". SPOffset = " << SPOffset
|
|
|
|
|
<< "; DeallocSize= " << DeallocSize << "\n";
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return Next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void StackAllocationAnalysis::doConfluenceWithLP(BitVector &StateOut,
|
|
|
|
|
const BitVector &StateIn,
|
|
|
|
|
const MCInst &Invoke) {
|
|
|
|
|
BitVector NewIn = StateIn;
|
2021-04-08 00:19:26 -07:00
|
|
|
const int64_t GnuArgsSize = BC.MIB->getGnuArgsSize(Invoke);
|
[BOLT][Refactoring] Isolate changes to MC layer
Summary:
Changes that we made to MCInst, MCOperand, MCExpr, etc. are now all
moved into tools/llvm-bolt. That required a change to the way we handle
annotations and any extra operands for MCInst.
Any MCPlus information is now attached via an extra operand of type
MCInst with an opcode ANNOTATION_LABEL. Since this operand is MCInst, we
attach extra info as operands to this instruction. For first-level
annotations use functions to access the information, such as
getConditionalTailCall() or getEHInfo(), etc. For the rest, optional or
second-class annotations, use a general named-annotation interface such
as getAnnotationAs<uint64_t>(Inst, "Count").
I did a test on HHVM binary, and a memory consumption went down a little
bit while the runtime remained the same.
(cherry picked from FBD7405412)
2018-03-19 18:32:12 -07:00
|
|
|
if (GnuArgsSize >= 0)
|
|
|
|
|
NewIn = doKill(Invoke, NewIn, GnuArgsSize);
|
2017-05-01 16:52:54 -07:00
|
|
|
StateOut |= NewIn;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BitVector StackAllocationAnalysis::computeNext(const MCInst &Point,
|
|
|
|
|
const BitVector &Cur) {
|
2018-03-09 09:45:13 -08:00
|
|
|
const auto &MIB = BC.MIB;
|
2017-05-01 16:52:54 -07:00
|
|
|
BitVector Next = Cur;
|
2018-03-09 09:45:13 -08:00
|
|
|
if (int Sz = MIB->getPopSize(Point)) {
|
2017-05-01 16:52:54 -07:00
|
|
|
Next = doKill(Point, Next, Sz);
|
|
|
|
|
return Next;
|
|
|
|
|
}
|
2018-03-09 09:45:13 -08:00
|
|
|
if (MIB->isPush(Point)) {
|
2017-05-01 16:52:54 -07:00
|
|
|
Next.set(this->ExprToIdx[&Point]);
|
|
|
|
|
return Next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MCPhysReg From, To;
|
|
|
|
|
int64_t SPOffset, FPOffset;
|
|
|
|
|
std::tie(SPOffset, FPOffset) = *SPT.getStateBefore(Point);
|
2018-03-09 09:45:13 -08:00
|
|
|
if (MIB->isRegToRegMove(Point, From, To) && To == MIB->getStackPointer() &&
|
|
|
|
|
From == MIB->getFramePointer()) {
|
|
|
|
|
if (MIB->isLeave(Point))
|
2017-05-01 16:52:54 -07:00
|
|
|
FPOffset += 8;
|
|
|
|
|
if (SPOffset < FPOffset) {
|
|
|
|
|
Next = doKill(Point, Next, FPOffset - SPOffset);
|
|
|
|
|
return Next;
|
|
|
|
|
}
|
|
|
|
|
if (SPOffset > FPOffset) {
|
|
|
|
|
Next.set(this->ExprToIdx[&Point]);
|
|
|
|
|
return Next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (BC.MII->get(Point.getOpcode())
|
2018-03-09 09:45:13 -08:00
|
|
|
.hasDefOfPhysReg(Point, MIB->getStackPointer(), *BC.MRI)) {
|
2017-05-01 16:52:54 -07:00
|
|
|
std::pair<MCPhysReg, int64_t> SP;
|
|
|
|
|
if (SPOffset != SPT.EMPTY && SPOffset != SPT.SUPERPOSITION)
|
2018-03-09 09:45:13 -08:00
|
|
|
SP = std::make_pair(MIB->getStackPointer(), SPOffset);
|
2017-05-01 16:52:54 -07:00
|
|
|
else
|
|
|
|
|
SP = std::make_pair(0, 0);
|
|
|
|
|
std::pair<MCPhysReg, int64_t> FP;
|
|
|
|
|
if (FPOffset != SPT.EMPTY && FPOffset != SPT.SUPERPOSITION)
|
2018-03-09 09:45:13 -08:00
|
|
|
FP = std::make_pair(MIB->getFramePointer(), FPOffset);
|
2017-05-01 16:52:54 -07:00
|
|
|
else
|
|
|
|
|
FP = std::make_pair(0, 0);
|
|
|
|
|
int64_t Output;
|
2022-05-20 17:42:58 -07:00
|
|
|
if (!MIB->evaluateStackOffsetExpr(Point, Output, SP, FP))
|
2017-05-01 16:52:54 -07:00
|
|
|
return Next;
|
|
|
|
|
|
|
|
|
|
if (SPOffset < Output) {
|
|
|
|
|
Next = doKill(Point, Next, Output - SPOffset);
|
|
|
|
|
return Next;
|
|
|
|
|
}
|
|
|
|
|
if (SPOffset > Output) {
|
|
|
|
|
Next.set(this->ExprToIdx[&Point]);
|
|
|
|
|
return Next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return Next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // end namespace bolt
|
|
|
|
|
} // end namespace llvm
|