LLVM 20.0.0git
PPCTOCRegDeps.cpp
Go to the documentation of this file.
1//===-- PPCTOCRegDeps.cpp - Add Extra TOC Register Dependencies -----------===//
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// When resolving an address using the ELF ABI TOC pointer, two relocations are
10// generally required: one for the high part and one for the low part. Only
11// the high part generally explicitly depends on r2 (the TOC pointer). And, so,
12// we might produce code like this:
13//
14// .Ltmp526:
15// addis 3, 2, .LC12@toc@ha
16// .Ltmp1628:
17// std 2, 40(1)
18// ld 5, 0(27)
19// ld 2, 8(27)
20// ld 11, 16(27)
21// ld 3, .LC12@toc@l(3)
22// rldicl 4, 4, 0, 32
23// mtctr 5
24// bctrl
25// ld 2, 40(1)
26//
27// And there is nothing wrong with this code, as such, but there is a linker bug
28// in binutils (https://sourceware.org/bugzilla/show_bug.cgi?id=18414) that will
29// misoptimize this code sequence to this:
30// nop
31// std r2,40(r1)
32// ld r5,0(r27)
33// ld r2,8(r27)
34// ld r11,16(r27)
35// ld r3,-32472(r2)
36// clrldi r4,r4,32
37// mtctr r5
38// bctrl
39// ld r2,40(r1)
40// because the linker does not know (and does not check) that the value in r2
41// changed in between the instruction using the .LC12@toc@ha (TOC-relative)
42// relocation and the instruction using the .LC12@toc@l(3) relocation.
43// Because it finds these instructions using the relocations (and not by
44// scanning the instructions), it has been asserted that there is no good way
45// to detect the change of r2 in between. As a result, this bug may never be
46// fixed (i.e. it may become part of the definition of the ABI). GCC was
47// updated to add extra dependencies on r2 to instructions using the @toc@l
48// relocations to avoid this problem, and we'll do the same here.
49//
50// This is done as a separate pass because:
51// 1. These extra r2 dependencies are not really properties of the
52// instructions, but rather due to a linker bug, and maybe one day we'll be
53// able to get rid of them when targeting linkers without this bug (and,
54// thus, keeping the logic centralized here will make that
55// straightforward).
56// 2. There are ISel-level peephole optimizations that propagate the @toc@l
57// relocations to some user instructions, and so the exta dependencies do
58// not apply only to a fixed set of instructions (without undesirable
59// definition replication).
60//
61//===----------------------------------------------------------------------===//
62
63#include "PPC.h"
64#include "PPCInstrInfo.h"
65#include "PPCTargetMachine.h"
66#include "llvm/ADT/STLExtras.h"
67#include "llvm/ADT/Statistic.h"
72
73using namespace llvm;
74
75#define DEBUG_TYPE "ppc-toc-reg-deps"
76
77namespace {
78 // PPCTOCRegDeps pass - For simple functions without epilogue code, move
79 // returns up, and create conditional returns, to avoid unnecessary
80 // branch-to-blr sequences.
81 struct PPCTOCRegDeps : public MachineFunctionPass {
82 static char ID;
83 PPCTOCRegDeps() : MachineFunctionPass(ID) {
85 }
86
87protected:
88 bool hasTOCLoReloc(const MachineInstr &MI) {
89 if (MI.getOpcode() == PPC::LDtocL || MI.getOpcode() == PPC::ADDItocL8 ||
90 MI.getOpcode() == PPC::LWZtocL)
91 return true;
92
93 for (const MachineOperand &MO : MI.operands()) {
94 if (MO.getTargetFlags() == PPCII::MO_TOC_LO)
95 return true;
96 }
97
98 return false;
99 }
100
101 bool processBlock(MachineBasicBlock &MBB) {
102 bool Changed = false;
103
104 const bool isPPC64 =
105 MBB.getParent()->getSubtarget<PPCSubtarget>().isPPC64();
106 const unsigned TOCReg = isPPC64 ? PPC::X2 : PPC::R2;
107
108 for (auto &MI : MBB) {
109 if (!hasTOCLoReloc(MI))
110 continue;
111
112 MI.addOperand(MachineOperand::CreateReg(TOCReg,
113 false /*IsDef*/,
114 true /*IsImp*/));
115 Changed = true;
116 }
117
118 return Changed;
119 }
120
121public:
122 bool runOnMachineFunction(MachineFunction &MF) override {
123 bool Changed = false;
124
126 if (processBlock(B))
127 Changed = true;
128
129 return Changed;
130 }
131
132 void getAnalysisUsage(AnalysisUsage &AU) const override {
134 }
135 };
136}
137
138INITIALIZE_PASS(PPCTOCRegDeps, DEBUG_TYPE,
139 "PowerPC TOC Register Dependencies", false, false)
140
141char PPCTOCRegDeps::ID = 0;
143llvm::createPPCTOCRegDepsPass() { return new PPCTOCRegDeps(); }
144
MachineBasicBlock & MBB
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
IRTranslator LLVM IR MI
#define DEBUG_TYPE
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
This file contains some templates that are useful if you are working with the STL at all.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
Represent the analysis usage information of a pass.
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:310
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Representation of each machine instruction.
Definition: MachineInstr.h:69
MachineOperand class - Representation of each machine instruction operand.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
@ MO_TOC_LO
Definition: PPC.h:183
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition: STLExtras.h:657
void initializePPCTOCRegDepsPass(PassRegistry &)
FunctionPass * createPPCTOCRegDepsPass()