12f09f445SMaksim Panchenko //===- bolt/Passes/AllocCombiner.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 // 92f09f445SMaksim Panchenko // This file implements the AllocCombinerPass class. 102f09f445SMaksim Panchenko // 11a34c753fSRafael Auler //===----------------------------------------------------------------------===// 12a34c753fSRafael Auler 13a34c753fSRafael Auler #include "bolt/Passes/AllocCombiner.h" 14a34c753fSRafael Auler 15a34c753fSRafael Auler #define DEBUG_TYPE "alloccombiner" 16a34c753fSRafael Auler 17a34c753fSRafael Auler using namespace llvm; 18a34c753fSRafael Auler 19a34c753fSRafael Auler namespace opts { 20a34c753fSRafael Auler 21a34c753fSRafael Auler extern cl::opt<bolt::FrameOptimizationType> FrameOptimization; 22a34c753fSRafael Auler 23a34c753fSRafael Auler } // end namespace opts 24a34c753fSRafael Auler 25a34c753fSRafael Auler namespace llvm { 26a34c753fSRafael Auler namespace bolt { 27a34c753fSRafael Auler 28a34c753fSRafael Auler namespace { 29a34c753fSRafael Auler 30a34c753fSRafael Auler bool getStackAdjustmentSize(const BinaryContext &BC, const MCInst &Inst, 31a34c753fSRafael Auler int64_t &Adjustment) { 32c09cd64eSRafael Auler return BC.MIB->evaluateStackOffsetExpr( 33c09cd64eSRafael Auler Inst, Adjustment, std::make_pair(BC.MIB->getStackPointer(), 0LL), 34a34c753fSRafael Auler std::make_pair(0, 0LL)); 35a34c753fSRafael Auler } 36a34c753fSRafael Auler 37a34c753fSRafael Auler bool isIndifferentToSP(const MCInst &Inst, const BinaryContext &BC) { 38a34c753fSRafael Auler if (BC.MIB->isCFI(Inst)) 39a34c753fSRafael Auler return true; 40a34c753fSRafael Auler 41a34c753fSRafael Auler const MCInstrDesc II = BC.MII->get(Inst.getOpcode()); 42a34c753fSRafael Auler if (BC.MIB->isTerminator(Inst) || 43a34c753fSRafael Auler II.hasImplicitDefOfPhysReg(BC.MIB->getStackPointer(), BC.MRI.get()) || 44a34c753fSRafael Auler II.hasImplicitUseOfPhysReg(BC.MIB->getStackPointer())) 45a34c753fSRafael Auler return false; 46a34c753fSRafael Auler 478cb7a873SAmir Ayupov for (const MCOperand &Operand : MCPlus::primeOperands(Inst)) 48f92ab6afSAmir Ayupov if (Operand.isReg() && Operand.getReg() == BC.MIB->getStackPointer()) 49a34c753fSRafael Auler return false; 50a34c753fSRafael Auler return true; 51a34c753fSRafael Auler } 52a34c753fSRafael Auler 53a34c753fSRafael Auler bool shouldProcess(const BinaryFunction &Function) { 54a34c753fSRafael Auler return Function.isSimple() && Function.hasCFG() && !Function.isIgnored(); 55a34c753fSRafael Auler } 56a34c753fSRafael Auler 57a34c753fSRafael Auler void runForAllWeCare(std::map<uint64_t, BinaryFunction> &BFs, 58a34c753fSRafael Auler std::function<void(BinaryFunction &)> Task) { 59a34c753fSRafael Auler for (auto &It : BFs) { 60a34c753fSRafael Auler BinaryFunction &Function = It.second; 61a34c753fSRafael Auler if (shouldProcess(Function)) 62a34c753fSRafael Auler Task(Function); 63a34c753fSRafael Auler } 64a34c753fSRafael Auler } 65a34c753fSRafael Auler 66a34c753fSRafael Auler } // end anonymous namespace 67a34c753fSRafael Auler 6860b09997SMaksim Panchenko void AllocCombinerPass::combineAdjustments(BinaryFunction &BF) { 6960b09997SMaksim Panchenko BinaryContext &BC = BF.getBinaryContext(); 70a34c753fSRafael Auler for (BinaryBasicBlock &BB : BF) { 71a34c753fSRafael Auler MCInst *Prev = nullptr; 72*f40d25ddSAmir Ayupov for (MCInst &Inst : llvm::reverse(BB)) { 73a34c753fSRafael Auler if (isIndifferentToSP(Inst, BC)) 74a34c753fSRafael Auler continue; // Skip updating Prev 75a34c753fSRafael Auler 76a34c753fSRafael Auler int64_t Adjustment = 0LL; 77a34c753fSRafael Auler if (!Prev || !BC.MIB->isStackAdjustment(Inst) || 78a34c753fSRafael Auler !BC.MIB->isStackAdjustment(*Prev) || 79a34c753fSRafael Auler !getStackAdjustmentSize(BC, *Prev, Adjustment)) { 80a34c753fSRafael Auler Prev = &Inst; 81a34c753fSRafael Auler continue; 82a34c753fSRafael Auler } 83a34c753fSRafael Auler 84a34c753fSRafael Auler LLVM_DEBUG({ 85a34c753fSRafael Auler dbgs() << "At \"" << BF.getPrintName() << "\", combining: \n"; 86a34c753fSRafael Auler Inst.dump(); 87a34c753fSRafael Auler Prev->dump(); 88a34c753fSRafael Auler dbgs() << "Adjustment: " << Adjustment << "\n"; 89a34c753fSRafael Auler }); 90a34c753fSRafael Auler 91a34c753fSRafael Auler if (BC.MIB->isSUB(Inst)) 92a34c753fSRafael Auler Adjustment = -Adjustment; 93a34c753fSRafael Auler 94a34c753fSRafael Auler BC.MIB->addToImm(Inst, Adjustment, BC.Ctx.get()); 95a34c753fSRafael Auler 96a34c753fSRafael Auler LLVM_DEBUG({ 97a34c753fSRafael Auler dbgs() << "After adjustment:\n"; 98a34c753fSRafael Auler Inst.dump(); 99a34c753fSRafael Auler }); 100a34c753fSRafael Auler 101a34c753fSRafael Auler BB.eraseInstruction(BB.findInstruction(Prev)); 102a34c753fSRafael Auler ++NumCombined; 10342465efdSRafael Auler DynamicCountCombined += BB.getKnownExecutionCount(); 104a34c753fSRafael Auler FuncsChanged.insert(&BF); 105a34c753fSRafael Auler Prev = &Inst; 106a34c753fSRafael Auler } 107a34c753fSRafael Auler } 108a34c753fSRafael Auler } 109a34c753fSRafael Auler 110a34c753fSRafael Auler void AllocCombinerPass::runOnFunctions(BinaryContext &BC) { 111a34c753fSRafael Auler if (opts::FrameOptimization == FOP_NONE) 112a34c753fSRafael Auler return; 113a34c753fSRafael Auler 11460b09997SMaksim Panchenko runForAllWeCare(BC.getBinaryFunctions(), [&](BinaryFunction &Function) { 11560b09997SMaksim Panchenko combineAdjustments(Function); 11660b09997SMaksim Panchenko }); 117a34c753fSRafael Auler 118a34c753fSRafael Auler outs() << "BOLT-INFO: Allocation combiner: " << NumCombined 11942465efdSRafael Auler << " empty spaces coalesced (dyn count: " << DynamicCountCombined 12042465efdSRafael Auler << ").\n"; 121a34c753fSRafael Auler } 122a34c753fSRafael Auler 123a34c753fSRafael Auler } // end namespace bolt 124a34c753fSRafael Auler } // end namespace llvm 125