blob: e0faae057c2225be67d078810ac21b0569e653b0 [file] [log] [blame]
Hal Finkelfc353912016-03-31 20:39:41 +00001//===----- PPCQPXLoadSplat.cpp - QPX Load Splat Simplification ------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Hal Finkelfc353912016-03-31 20:39:41 +00006//
7//===----------------------------------------------------------------------===//
8//
9// The QPX vector registers overlay the scalar floating-point registers, and
10// any scalar floating-point loads splat their value across all vector lanes.
11// Thus, if we have a scalar load followed by a splat, we can remove the splat
12// (i.e. replace the load with a load-and-splat pseudo instruction).
13//
14// This pass must run after anything that might do store-to-load forwarding.
15//
16//===----------------------------------------------------------------------===//
17
18#include "PPC.h"
19#include "PPCInstrBuilder.h"
20#include "PPCInstrInfo.h"
21#include "llvm/ADT/SmallVector.h"
22#include "llvm/ADT/Statistic.h"
23#include "llvm/CodeGen/MachineFunctionPass.h"
David Blaikieb3bde2e2017-11-17 01:07:10 +000024#include "llvm/CodeGen/TargetSubtargetInfo.h"
Hal Finkelfc353912016-03-31 20:39:41 +000025#include "llvm/Support/MathExtras.h"
26#include "llvm/Target/TargetMachine.h"
Hal Finkelfc353912016-03-31 20:39:41 +000027using namespace llvm;
28
29#define DEBUG_TYPE "ppc-qpx-load-splat"
30
31STATISTIC(NumSimplified, "Number of QPX load splats simplified");
32
33namespace llvm {
34 void initializePPCQPXLoadSplatPass(PassRegistry&);
35}
36
37namespace {
38 struct PPCQPXLoadSplat : public MachineFunctionPass {
39 static char ID;
40 PPCQPXLoadSplat() : MachineFunctionPass(ID) {
41 initializePPCQPXLoadSplatPass(*PassRegistry::getPassRegistry());
42 }
43
44 bool runOnMachineFunction(MachineFunction &Fn) override;
45
Mehdi Amini117296c2016-10-01 02:56:57 +000046 StringRef getPassName() const override {
Hal Finkelfc353912016-03-31 20:39:41 +000047 return "PowerPC QPX Load Splat Simplification";
48 }
49 };
50 char PPCQPXLoadSplat::ID = 0;
51}
52
53INITIALIZE_PASS(PPCQPXLoadSplat, "ppc-qpx-load-splat",
54 "PowerPC QPX Load Splat Simplification",
55 false, false)
56
57FunctionPass *llvm::createPPCQPXLoadSplatPass() {
58 return new PPCQPXLoadSplat();
59}
60
61bool PPCQPXLoadSplat::runOnMachineFunction(MachineFunction &MF) {
Matthias Braunf1caa282017-12-15 22:22:58 +000062 if (skipFunction(MF.getFunction()))
Andrew Kaylor289bd5f2016-04-27 19:39:32 +000063 return false;
64
Hal Finkelfc353912016-03-31 20:39:41 +000065 bool MadeChange = false;
66 const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
67
68 for (auto MFI = MF.begin(), MFIE = MF.end(); MFI != MFIE; ++MFI) {
69 MachineBasicBlock *MBB = &*MFI;
70 SmallVector<MachineInstr *, 4> Splats;
71
72 for (auto MBBI = MBB->rbegin(); MBBI != MBB->rend(); ++MBBI) {
73 MachineInstr *MI = &*MBBI;
74
75 if (MI->hasUnmodeledSideEffects() || MI->isCall()) {
76 Splats.clear();
77 continue;
78 }
79
80 // We're looking for a sequence like this:
Francis Visoiu Mistriha8a83d12017-12-07 10:40:31 +000081 // %f0 = LFD 0, killed %x3, implicit-def %qf0; mem:LD8[%a](tbaa=!2)
82 // %qf1 = QVESPLATI killed %qf0, 0, implicit %rm
Hal Finkelfc353912016-03-31 20:39:41 +000083
84 for (auto SI = Splats.begin(); SI != Splats.end();) {
85 MachineInstr *SMI = *SI;
86 unsigned SplatReg = SMI->getOperand(0).getReg();
87 unsigned SrcReg = SMI->getOperand(1).getReg();
88
89 if (MI->modifiesRegister(SrcReg, TRI)) {
90 switch (MI->getOpcode()) {
91 default:
92 SI = Splats.erase(SI);
93 continue;
94 case PPC::LFS:
95 case PPC::LFD:
96 case PPC::LFSU:
97 case PPC::LFDU:
98 case PPC::LFSUX:
99 case PPC::LFDUX:
100 case PPC::LFSX:
101 case PPC::LFDX:
102 case PPC::LFIWAX:
103 case PPC::LFIWZX:
104 if (SplatReg != SrcReg) {
105 // We need to change the load to define the scalar subregister of
106 // the QPX splat source register.
107 unsigned SubRegIndex =
108 TRI->getSubRegIndex(SrcReg, MI->getOperand(0).getReg());
109 unsigned SplatSubReg = TRI->getSubReg(SplatReg, SubRegIndex);
110
111 // Substitute both the explicit defined register, and also the
112 // implicit def of the containing QPX register.
113 MI->getOperand(0).setReg(SplatSubReg);
114 MI->substituteRegister(SrcReg, SplatReg, 0, *TRI);
115 }
116
117 SI = Splats.erase(SI);
118
119 // If SMI is directly after MI, then MBBI's base iterator is
120 // pointing at SMI. Adjust MBBI around the call to erase SMI to
121 // avoid invalidating MBBI.
122 ++MBBI;
123 SMI->eraseFromParent();
124 --MBBI;
125
126 ++NumSimplified;
127 MadeChange = true;
128 continue;
129 }
130 }
131
NAKAMURA Takumife1202c2016-06-20 00:37:41 +0000132 // If this instruction defines the splat register, then we cannot move
133 // the previous definition above it. If it reads from the splat
134 // register, then it must already be alive from some previous
135 // definition, and if the splat register is different from the source
136 // register, then this definition must not be the load for which we're
137 // searching.
Hal Finkel17e97542016-04-30 01:59:28 +0000138 if (MI->modifiesRegister(SplatReg, TRI) ||
139 (SrcReg != SplatReg &&
140 MI->readsRegister(SplatReg, TRI))) {
Hal Finkelfc353912016-03-31 20:39:41 +0000141 SI = Splats.erase(SI);
142 continue;
143 }
144
145 ++SI;
146 }
147
148 if (MI->getOpcode() != PPC::QVESPLATI &&
149 MI->getOpcode() != PPC::QVESPLATIs &&
150 MI->getOpcode() != PPC::QVESPLATIb)
151 continue;
152 if (MI->getOperand(2).getImm() != 0)
153 continue;
154
155 // If there are other uses of the scalar value after this, replacing
156 // those uses might be non-trivial.
157 if (!MI->getOperand(1).isKill())
158 continue;
159
160 Splats.push_back(MI);
161 }
162 }
163
164 return MadeChange;
165}