LLVM 24.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"
73
74using namespace llvm;
75
76#define DEBUG_TYPE "ppc-toc-reg-deps"
77
78namespace {
79 // PPCTOCRegDeps pass - For simple functions without epilogue code, move
80 // returns up, and create conditional returns, to avoid unnecessary
81 // branch-to-blr sequences.
82 struct PPCTOCRegDeps : public MachineFunctionPass {
83 static char ID;
84 PPCTOCRegDeps() : MachineFunctionPass(ID) {}
85
86 protected:
87 bool hasTOCLoReloc(const MachineInstr &MI) {
88 if (MI.getOpcode() == PPC::LDtocL || MI.getOpcode() == PPC::ADDItocL8 ||
89 MI.getOpcode() == PPC::LWZtocL)
90 return true;
91
92 for (const MachineOperand &MO : MI.operands()) {
93 if (MO.getTargetFlags() == PPCII::MO_TOC_LO)
94 return true;
95 }
96
97 return false;
98 }
99
100 bool processBlock(MachineBasicBlock &MBB) {
101 bool Changed = false;
102
103 const bool isPPC64 =
104 MBB.getParent()->getSubtarget<PPCSubtarget>().isPPC64();
105 const unsigned TOCReg = isPPC64 ? PPC::X2 : PPC::R2;
106
107 for (auto &MI : MBB) {
108 if (!hasTOCLoReloc(MI))
109 continue;
110
111 MI.addOperand(MachineOperand::CreateReg(TOCReg,
112 false /*IsDef*/,
113 true /*IsImp*/));
114 Changed = true;
115 }
116
117 return Changed;
118 }
119
120public:
121 bool runOnMachineFunction(MachineFunction &MF) override {
122 bool Changed = false;
123
125 if (processBlock(B))
126 Changed = true;
127
128 return Changed;
129 }
130
131 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")
#define DEBUG_TYPE
IRTranslator LLVM IR MI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
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.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
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.
Representation of each machine instruction.
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)
Changed
@ MO_TOC_LO
Definition PPC.h:187
This is an optimization pass for GlobalISel generic memory operations.
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:633
FunctionPass * createPPCTOCRegDepsPass()