1 //===- bolt/Passes/ADRRelaxationPass.cpp ----------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements the ADRRelaxationPass class. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "bolt/Passes/ADRRelaxationPass.h" 14 #include "bolt/Core/ParallelUtilities.h" 15 16 using namespace llvm; 17 18 namespace opts { 19 extern cl::OptionCategory BoltCategory; 20 21 static cl::opt<bool> 22 AdrPassOpt("adr-relaxation", 23 cl::desc("Replace ARM non-local ADR instructions with ADRP"), 24 cl::init(true), cl::cat(BoltCategory), cl::ReallyHidden); 25 } // namespace opts 26 27 namespace llvm { 28 namespace bolt { 29 30 void ADRRelaxationPass::runOnFunction(BinaryFunction &BF) { 31 BinaryContext &BC = BF.getBinaryContext(); 32 for (BinaryBasicBlock *BB : BF.layout()) { 33 for (auto It = BB->begin(); It != BB->end(); ++It) { 34 MCInst &Inst = *It; 35 if (!BC.MIB->isADR(Inst)) 36 continue; 37 38 const MCSymbol *Symbol = BC.MIB->getTargetSymbol(Inst); 39 if (!Symbol) 40 continue; 41 42 if (BF.hasIslandsInfo()) { 43 BinaryFunction::IslandInfo &Islands = BF.getIslandInfo(); 44 if (Islands.Symbols.count(Symbol) || Islands.ProxySymbols.count(Symbol)) 45 continue; 46 } 47 48 BinaryFunction *TargetBF = BC.getFunctionForSymbol(Symbol); 49 if (TargetBF && TargetBF == &BF) 50 continue; 51 52 MCPhysReg Reg; 53 BC.MIB->getADRReg(Inst, Reg); 54 int64_t Addend = BC.MIB->getTargetAddend(Inst); 55 InstructionListType Addr = 56 BC.MIB->materializeAddress(Symbol, BC.Ctx.get(), Reg, Addend); 57 It = BB->replaceInstruction(It, Addr); 58 } 59 } 60 } 61 62 void ADRRelaxationPass::runOnFunctions(BinaryContext &BC) { 63 if (!opts::AdrPassOpt || !BC.HasRelocations) 64 return; 65 66 ParallelUtilities::WorkFuncTy WorkFun = [&](BinaryFunction &BF) { 67 runOnFunction(BF); 68 }; 69 70 ParallelUtilities::runOnEachFunction( 71 BC, ParallelUtilities::SchedulingPolicy::SP_TRIVIAL, WorkFun, nullptr, 72 "ADRRelaxationPass", /* ForceSequential */ true); 73 } 74 75 } // end namespace bolt 76 } // end namespace llvm 77