10b57cec5SDimitry Andric //===-- PPCTOCRegDeps.cpp - Add Extra TOC Register Dependencies -----------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // When resolving an address using the ELF ABI TOC pointer, two relocations are 100b57cec5SDimitry Andric // generally required: one for the high part and one for the low part. Only 110b57cec5SDimitry Andric // the high part generally explicitly depends on r2 (the TOC pointer). And, so, 120b57cec5SDimitry Andric // we might produce code like this: 130b57cec5SDimitry Andric // 140b57cec5SDimitry Andric // .Ltmp526: 150b57cec5SDimitry Andric // addis 3, 2, .LC12@toc@ha 160b57cec5SDimitry Andric // .Ltmp1628: 170b57cec5SDimitry Andric // std 2, 40(1) 180b57cec5SDimitry Andric // ld 5, 0(27) 190b57cec5SDimitry Andric // ld 2, 8(27) 200b57cec5SDimitry Andric // ld 11, 16(27) 210b57cec5SDimitry Andric // ld 3, .LC12@toc@l(3) 220b57cec5SDimitry Andric // rldicl 4, 4, 0, 32 230b57cec5SDimitry Andric // mtctr 5 240b57cec5SDimitry Andric // bctrl 250b57cec5SDimitry Andric // ld 2, 40(1) 260b57cec5SDimitry Andric // 270b57cec5SDimitry Andric // And there is nothing wrong with this code, as such, but there is a linker bug 280b57cec5SDimitry Andric // in binutils (https://sourceware.org/bugzilla/show_bug.cgi?id=18414) that will 290b57cec5SDimitry Andric // misoptimize this code sequence to this: 300b57cec5SDimitry Andric // nop 310b57cec5SDimitry Andric // std r2,40(r1) 320b57cec5SDimitry Andric // ld r5,0(r27) 330b57cec5SDimitry Andric // ld r2,8(r27) 340b57cec5SDimitry Andric // ld r11,16(r27) 350b57cec5SDimitry Andric // ld r3,-32472(r2) 360b57cec5SDimitry Andric // clrldi r4,r4,32 370b57cec5SDimitry Andric // mtctr r5 380b57cec5SDimitry Andric // bctrl 390b57cec5SDimitry Andric // ld r2,40(r1) 400b57cec5SDimitry Andric // because the linker does not know (and does not check) that the value in r2 410b57cec5SDimitry Andric // changed in between the instruction using the .LC12@toc@ha (TOC-relative) 420b57cec5SDimitry Andric // relocation and the instruction using the .LC12@toc@l(3) relocation. 430b57cec5SDimitry Andric // Because it finds these instructions using the relocations (and not by 440b57cec5SDimitry Andric // scanning the instructions), it has been asserted that there is no good way 450b57cec5SDimitry Andric // to detect the change of r2 in between. As a result, this bug may never be 460b57cec5SDimitry Andric // fixed (i.e. it may become part of the definition of the ABI). GCC was 470b57cec5SDimitry Andric // updated to add extra dependencies on r2 to instructions using the @toc@l 480b57cec5SDimitry Andric // relocations to avoid this problem, and we'll do the same here. 490b57cec5SDimitry Andric // 500b57cec5SDimitry Andric // This is done as a separate pass because: 510b57cec5SDimitry Andric // 1. These extra r2 dependencies are not really properties of the 520b57cec5SDimitry Andric // instructions, but rather due to a linker bug, and maybe one day we'll be 530b57cec5SDimitry Andric // able to get rid of them when targeting linkers without this bug (and, 540b57cec5SDimitry Andric // thus, keeping the logic centralized here will make that 550b57cec5SDimitry Andric // straightforward). 560b57cec5SDimitry Andric // 2. There are ISel-level peephole optimizations that propagate the @toc@l 570b57cec5SDimitry Andric // relocations to some user instructions, and so the exta dependencies do 580b57cec5SDimitry Andric // not apply only to a fixed set of instructions (without undesirable 590b57cec5SDimitry Andric // definition replication). 600b57cec5SDimitry Andric // 610b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric #include "MCTargetDesc/PPCPredicates.h" 640b57cec5SDimitry Andric #include "PPC.h" 650b57cec5SDimitry Andric #include "PPCInstrBuilder.h" 660b57cec5SDimitry Andric #include "PPCInstrInfo.h" 670b57cec5SDimitry Andric #include "PPCMachineFunctionInfo.h" 680b57cec5SDimitry Andric #include "PPCTargetMachine.h" 690b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 700b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h" 710b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 720b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 730b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 740b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 750b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h" 76349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h" 770b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 780b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 790b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 800b57cec5SDimitry Andric 810b57cec5SDimitry Andric using namespace llvm; 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric #define DEBUG_TYPE "ppc-toc-reg-deps" 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric namespace { 860b57cec5SDimitry Andric // PPCTOCRegDeps pass - For simple functions without epilogue code, move 870b57cec5SDimitry Andric // returns up, and create conditional returns, to avoid unnecessary 880b57cec5SDimitry Andric // branch-to-blr sequences. 890b57cec5SDimitry Andric struct PPCTOCRegDeps : public MachineFunctionPass { 900b57cec5SDimitry Andric static char ID; 910b57cec5SDimitry Andric PPCTOCRegDeps() : MachineFunctionPass(ID) { 920b57cec5SDimitry Andric initializePPCTOCRegDepsPass(*PassRegistry::getPassRegistry()); 930b57cec5SDimitry Andric } 940b57cec5SDimitry Andric 950b57cec5SDimitry Andric protected: 960b57cec5SDimitry Andric bool hasTOCLoReloc(const MachineInstr &MI) { 97*0fca6ea1SDimitry Andric if (MI.getOpcode() == PPC::LDtocL || MI.getOpcode() == PPC::ADDItocL8 || 988bcb0991SDimitry Andric MI.getOpcode() == PPC::LWZtocL) 990b57cec5SDimitry Andric return true; 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric for (const MachineOperand &MO : MI.operands()) { 1025f757f3fSDimitry Andric if (MO.getTargetFlags() == PPCII::MO_TOC_LO) 1030b57cec5SDimitry Andric return true; 1040b57cec5SDimitry Andric } 1050b57cec5SDimitry Andric 1060b57cec5SDimitry Andric return false; 1070b57cec5SDimitry Andric } 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric bool processBlock(MachineBasicBlock &MBB) { 1100b57cec5SDimitry Andric bool Changed = false; 1110b57cec5SDimitry Andric 1128bcb0991SDimitry Andric const bool isPPC64 = 1138bcb0991SDimitry Andric MBB.getParent()->getSubtarget<PPCSubtarget>().isPPC64(); 1148bcb0991SDimitry Andric const unsigned TOCReg = isPPC64 ? PPC::X2 : PPC::R2; 1158bcb0991SDimitry Andric 1160b57cec5SDimitry Andric for (auto &MI : MBB) { 1170b57cec5SDimitry Andric if (!hasTOCLoReloc(MI)) 1180b57cec5SDimitry Andric continue; 1190b57cec5SDimitry Andric 1208bcb0991SDimitry Andric MI.addOperand(MachineOperand::CreateReg(TOCReg, 1210b57cec5SDimitry Andric false /*IsDef*/, 1220b57cec5SDimitry Andric true /*IsImp*/)); 1230b57cec5SDimitry Andric Changed = true; 1240b57cec5SDimitry Andric } 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric return Changed; 1270b57cec5SDimitry Andric } 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric public: 1300b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override { 1310b57cec5SDimitry Andric bool Changed = false; 1320b57cec5SDimitry Andric 133349cc55cSDimitry Andric for (MachineBasicBlock &B : llvm::make_early_inc_range(MF)) 1340b57cec5SDimitry Andric if (processBlock(B)) 1350b57cec5SDimitry Andric Changed = true; 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric return Changed; 1380b57cec5SDimitry Andric } 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 1410b57cec5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 1420b57cec5SDimitry Andric } 1430b57cec5SDimitry Andric }; 1440b57cec5SDimitry Andric } 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andric INITIALIZE_PASS(PPCTOCRegDeps, DEBUG_TYPE, 1470b57cec5SDimitry Andric "PowerPC TOC Register Dependencies", false, false) 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric char PPCTOCRegDeps::ID = 0; 1500b57cec5SDimitry Andric FunctionPass* 1510b57cec5SDimitry Andric llvm::createPPCTOCRegDepsPass() { return new PPCTOCRegDeps(); } 1520b57cec5SDimitry Andric 153