LLVM 22.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) {}
84
85 protected:
86 bool hasTOCLoReloc(const MachineInstr &MI) {
87 if (MI.getOpcode() == PPC::LDtocL || MI.getOpcode() == PPC::ADDItocL8 ||
88 MI.getOpcode() == PPC::LWZtocL)
89 return true;
90
91 for (const MachineOperand &MO : MI.operands()) {
92 if (MO.getTargetFlags() == PPCII::MO_TOC_LO)
93 return true;
94 }
95
96 return false;
97 }
98
99 bool processBlock(MachineBasicBlock &MBB) {
100 bool Changed = false;
101
102 const bool isPPC64 =
103 MBB.getParent()->getSubtarget<PPCSubtarget>().isPPC64();
104 const unsigned TOCReg = isPPC64 ? PPC::X2 : PPC::R2;
105
106 for (auto &MI : MBB) {
107 if (!hasTOCLoReloc(MI))
108 continue;
109
110 MI.addOperand(MachineOperand::CreateReg(TOCReg,
111 false /*IsDef*/,
112 true /*IsImp*/));
113 Changed = true;
114 }
115
116 return Changed;
117 }
118
119public:
120 bool runOnMachineFunction(MachineFunction &MF) override {
121 bool Changed = false;
122
124 if (processBlock(B))
125 Changed = true;
126
127 return Changed;
128 }
129
130 void getAnalysisUsage(AnalysisUsage &AU) const override {
132 }
133 };
134}
135
136INITIALIZE_PASS(PPCTOCRegDeps, DEBUG_TYPE,
137 "PowerPC TOC Register Dependencies", false, false)
138
139char PPCTOCRegDeps::ID = 0;
141llvm::createPPCTOCRegDepsPass() { return new PPCTOCRegDeps(); }
142
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.
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
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ MO_TOC_LO
Definition PPC.h:185
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:646
FunctionPass * createPPCTOCRegDepsPass()