LLVM 17.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
64#include "PPC.h"
65#include "PPCInstrBuilder.h"
66#include "PPCInstrInfo.h"
68#include "PPCTargetMachine.h"
69#include "llvm/ADT/STLExtras.h"
70#include "llvm/ADT/Statistic.h"
75#include "llvm/MC/MCAsmInfo.h"
77#include "llvm/Support/Debug.h"
80
81using namespace llvm;
82
83#define DEBUG_TYPE "ppc-toc-reg-deps"
84
85namespace {
86 // PPCTOCRegDeps pass - For simple functions without epilogue code, move
87 // returns up, and create conditional returns, to avoid unnecessary
88 // branch-to-blr sequences.
89 struct PPCTOCRegDeps : public MachineFunctionPass {
90 static char ID;
91 PPCTOCRegDeps() : MachineFunctionPass(ID) {
93 }
94
95protected:
96 bool hasTOCLoReloc(const MachineInstr &MI) {
97 if (MI.getOpcode() == PPC::LDtocL ||
98 MI.getOpcode() == PPC::ADDItocL ||
99 MI.getOpcode() == PPC::LWZtocL)
100 return true;
101
102 for (const MachineOperand &MO : MI.operands()) {
103 if ((MO.getTargetFlags() & PPCII::MO_ACCESS_MASK) == PPCII::MO_TOC_LO)
104 return true;
105 }
106
107 return false;
108 }
109
110 bool processBlock(MachineBasicBlock &MBB) {
111 bool Changed = false;
112
113 const bool isPPC64 =
114 MBB.getParent()->getSubtarget<PPCSubtarget>().isPPC64();
115 const unsigned TOCReg = isPPC64 ? PPC::X2 : PPC::R2;
116
117 for (auto &MI : MBB) {
118 if (!hasTOCLoReloc(MI))
119 continue;
120
121 MI.addOperand(MachineOperand::CreateReg(TOCReg,
122 false /*IsDef*/,
123 true /*IsImp*/));
124 Changed = true;
125 }
126
127 return Changed;
128 }
129
130public:
131 bool runOnMachineFunction(MachineFunction &MF) override {
132 bool Changed = false;
133
135 if (processBlock(B))
136 Changed = true;
137
138 return Changed;
139 }
140
141 void getAnalysisUsage(AnalysisUsage &AU) const override {
143 }
144 };
145}
146
147INITIALIZE_PASS(PPCTOCRegDeps, DEBUG_TYPE,
148 "PowerPC TOC Register Dependencies", false, false)
149
150char PPCTOCRegDeps::ID = 0;
152llvm::createPPCTOCRegDepsPass() { return new PPCTOCRegDeps(); }
153
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:308
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:68
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_ACCESS_MASK
The next are not flags but distinct values.
Definition: PPC.h:158
@ MO_TOC_LO
Definition: PPC.h:171
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:721
void initializePPCTOCRegDepsPass(PassRegistry &)
FunctionPass * createPPCTOCRegDepsPass()