1*9880d681SAndroid Build Coastguard Worker //===----- PPCQPXLoadSplat.cpp - QPX Load Splat Simplification ------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // The QPX vector registers overlay the scalar floating-point registers, and
11*9880d681SAndroid Build Coastguard Worker // any scalar floating-point loads splat their value across all vector lanes.
12*9880d681SAndroid Build Coastguard Worker // Thus, if we have a scalar load followed by a splat, we can remove the splat
13*9880d681SAndroid Build Coastguard Worker // (i.e. replace the load with a load-and-splat pseudo instruction).
14*9880d681SAndroid Build Coastguard Worker //
15*9880d681SAndroid Build Coastguard Worker // This pass must run after anything that might do store-to-load forwarding.
16*9880d681SAndroid Build Coastguard Worker //
17*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
18*9880d681SAndroid Build Coastguard Worker
19*9880d681SAndroid Build Coastguard Worker #include "PPC.h"
20*9880d681SAndroid Build Coastguard Worker #include "PPCInstrBuilder.h"
21*9880d681SAndroid Build Coastguard Worker #include "PPCInstrInfo.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallVector.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Statistic.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunctionPass.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/MathExtras.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetMachine.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetSubtargetInfo.h"
28*9880d681SAndroid Build Coastguard Worker using namespace llvm;
29*9880d681SAndroid Build Coastguard Worker
30*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "ppc-qpx-load-splat"
31*9880d681SAndroid Build Coastguard Worker
32*9880d681SAndroid Build Coastguard Worker STATISTIC(NumSimplified, "Number of QPX load splats simplified");
33*9880d681SAndroid Build Coastguard Worker
34*9880d681SAndroid Build Coastguard Worker namespace llvm {
35*9880d681SAndroid Build Coastguard Worker void initializePPCQPXLoadSplatPass(PassRegistry&);
36*9880d681SAndroid Build Coastguard Worker }
37*9880d681SAndroid Build Coastguard Worker
38*9880d681SAndroid Build Coastguard Worker namespace {
39*9880d681SAndroid Build Coastguard Worker struct PPCQPXLoadSplat : public MachineFunctionPass {
40*9880d681SAndroid Build Coastguard Worker static char ID;
PPCQPXLoadSplat__anon8908f58d0111::PPCQPXLoadSplat41*9880d681SAndroid Build Coastguard Worker PPCQPXLoadSplat() : MachineFunctionPass(ID) {
42*9880d681SAndroid Build Coastguard Worker initializePPCQPXLoadSplatPass(*PassRegistry::getPassRegistry());
43*9880d681SAndroid Build Coastguard Worker }
44*9880d681SAndroid Build Coastguard Worker
45*9880d681SAndroid Build Coastguard Worker bool runOnMachineFunction(MachineFunction &Fn) override;
46*9880d681SAndroid Build Coastguard Worker
getPassName__anon8908f58d0111::PPCQPXLoadSplat47*9880d681SAndroid Build Coastguard Worker const char *getPassName() const override {
48*9880d681SAndroid Build Coastguard Worker return "PowerPC QPX Load Splat Simplification";
49*9880d681SAndroid Build Coastguard Worker }
50*9880d681SAndroid Build Coastguard Worker };
51*9880d681SAndroid Build Coastguard Worker char PPCQPXLoadSplat::ID = 0;
52*9880d681SAndroid Build Coastguard Worker }
53*9880d681SAndroid Build Coastguard Worker
54*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS(PPCQPXLoadSplat, "ppc-qpx-load-splat",
55*9880d681SAndroid Build Coastguard Worker "PowerPC QPX Load Splat Simplification",
56*9880d681SAndroid Build Coastguard Worker false, false)
57*9880d681SAndroid Build Coastguard Worker
createPPCQPXLoadSplatPass()58*9880d681SAndroid Build Coastguard Worker FunctionPass *llvm::createPPCQPXLoadSplatPass() {
59*9880d681SAndroid Build Coastguard Worker return new PPCQPXLoadSplat();
60*9880d681SAndroid Build Coastguard Worker }
61*9880d681SAndroid Build Coastguard Worker
runOnMachineFunction(MachineFunction & MF)62*9880d681SAndroid Build Coastguard Worker bool PPCQPXLoadSplat::runOnMachineFunction(MachineFunction &MF) {
63*9880d681SAndroid Build Coastguard Worker if (skipFunction(*MF.getFunction()))
64*9880d681SAndroid Build Coastguard Worker return false;
65*9880d681SAndroid Build Coastguard Worker
66*9880d681SAndroid Build Coastguard Worker bool MadeChange = false;
67*9880d681SAndroid Build Coastguard Worker const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
68*9880d681SAndroid Build Coastguard Worker
69*9880d681SAndroid Build Coastguard Worker for (auto MFI = MF.begin(), MFIE = MF.end(); MFI != MFIE; ++MFI) {
70*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *MBB = &*MFI;
71*9880d681SAndroid Build Coastguard Worker SmallVector<MachineInstr *, 4> Splats;
72*9880d681SAndroid Build Coastguard Worker
73*9880d681SAndroid Build Coastguard Worker for (auto MBBI = MBB->rbegin(); MBBI != MBB->rend(); ++MBBI) {
74*9880d681SAndroid Build Coastguard Worker MachineInstr *MI = &*MBBI;
75*9880d681SAndroid Build Coastguard Worker
76*9880d681SAndroid Build Coastguard Worker if (MI->hasUnmodeledSideEffects() || MI->isCall()) {
77*9880d681SAndroid Build Coastguard Worker Splats.clear();
78*9880d681SAndroid Build Coastguard Worker continue;
79*9880d681SAndroid Build Coastguard Worker }
80*9880d681SAndroid Build Coastguard Worker
81*9880d681SAndroid Build Coastguard Worker // We're looking for a sequence like this:
82*9880d681SAndroid Build Coastguard Worker // %F0<def> = LFD 0, %X3<kill>, %QF0<imp-def>; mem:LD8[%a](tbaa=!2)
83*9880d681SAndroid Build Coastguard Worker // %QF1<def> = QVESPLATI %QF0<kill>, 0, %RM<imp-use>
84*9880d681SAndroid Build Coastguard Worker
85*9880d681SAndroid Build Coastguard Worker for (auto SI = Splats.begin(); SI != Splats.end();) {
86*9880d681SAndroid Build Coastguard Worker MachineInstr *SMI = *SI;
87*9880d681SAndroid Build Coastguard Worker unsigned SplatReg = SMI->getOperand(0).getReg();
88*9880d681SAndroid Build Coastguard Worker unsigned SrcReg = SMI->getOperand(1).getReg();
89*9880d681SAndroid Build Coastguard Worker
90*9880d681SAndroid Build Coastguard Worker if (MI->modifiesRegister(SrcReg, TRI)) {
91*9880d681SAndroid Build Coastguard Worker switch (MI->getOpcode()) {
92*9880d681SAndroid Build Coastguard Worker default:
93*9880d681SAndroid Build Coastguard Worker SI = Splats.erase(SI);
94*9880d681SAndroid Build Coastguard Worker continue;
95*9880d681SAndroid Build Coastguard Worker case PPC::LFS:
96*9880d681SAndroid Build Coastguard Worker case PPC::LFD:
97*9880d681SAndroid Build Coastguard Worker case PPC::LFSU:
98*9880d681SAndroid Build Coastguard Worker case PPC::LFDU:
99*9880d681SAndroid Build Coastguard Worker case PPC::LFSUX:
100*9880d681SAndroid Build Coastguard Worker case PPC::LFDUX:
101*9880d681SAndroid Build Coastguard Worker case PPC::LFSX:
102*9880d681SAndroid Build Coastguard Worker case PPC::LFDX:
103*9880d681SAndroid Build Coastguard Worker case PPC::LFIWAX:
104*9880d681SAndroid Build Coastguard Worker case PPC::LFIWZX:
105*9880d681SAndroid Build Coastguard Worker if (SplatReg != SrcReg) {
106*9880d681SAndroid Build Coastguard Worker // We need to change the load to define the scalar subregister of
107*9880d681SAndroid Build Coastguard Worker // the QPX splat source register.
108*9880d681SAndroid Build Coastguard Worker unsigned SubRegIndex =
109*9880d681SAndroid Build Coastguard Worker TRI->getSubRegIndex(SrcReg, MI->getOperand(0).getReg());
110*9880d681SAndroid Build Coastguard Worker unsigned SplatSubReg = TRI->getSubReg(SplatReg, SubRegIndex);
111*9880d681SAndroid Build Coastguard Worker
112*9880d681SAndroid Build Coastguard Worker // Substitute both the explicit defined register, and also the
113*9880d681SAndroid Build Coastguard Worker // implicit def of the containing QPX register.
114*9880d681SAndroid Build Coastguard Worker MI->getOperand(0).setReg(SplatSubReg);
115*9880d681SAndroid Build Coastguard Worker MI->substituteRegister(SrcReg, SplatReg, 0, *TRI);
116*9880d681SAndroid Build Coastguard Worker }
117*9880d681SAndroid Build Coastguard Worker
118*9880d681SAndroid Build Coastguard Worker SI = Splats.erase(SI);
119*9880d681SAndroid Build Coastguard Worker
120*9880d681SAndroid Build Coastguard Worker // If SMI is directly after MI, then MBBI's base iterator is
121*9880d681SAndroid Build Coastguard Worker // pointing at SMI. Adjust MBBI around the call to erase SMI to
122*9880d681SAndroid Build Coastguard Worker // avoid invalidating MBBI.
123*9880d681SAndroid Build Coastguard Worker ++MBBI;
124*9880d681SAndroid Build Coastguard Worker SMI->eraseFromParent();
125*9880d681SAndroid Build Coastguard Worker --MBBI;
126*9880d681SAndroid Build Coastguard Worker
127*9880d681SAndroid Build Coastguard Worker ++NumSimplified;
128*9880d681SAndroid Build Coastguard Worker MadeChange = true;
129*9880d681SAndroid Build Coastguard Worker continue;
130*9880d681SAndroid Build Coastguard Worker }
131*9880d681SAndroid Build Coastguard Worker }
132*9880d681SAndroid Build Coastguard Worker
133*9880d681SAndroid Build Coastguard Worker // If this instruction defines the splat register, then we cannot move
134*9880d681SAndroid Build Coastguard Worker // the previous definition above it. If it reads from the splat
135*9880d681SAndroid Build Coastguard Worker // register, then it must already be alive from some previous
136*9880d681SAndroid Build Coastguard Worker // definition, and if the splat register is different from the source
137*9880d681SAndroid Build Coastguard Worker // register, then this definition must not be the load for which we're
138*9880d681SAndroid Build Coastguard Worker // searching.
139*9880d681SAndroid Build Coastguard Worker if (MI->modifiesRegister(SplatReg, TRI) ||
140*9880d681SAndroid Build Coastguard Worker (SrcReg != SplatReg &&
141*9880d681SAndroid Build Coastguard Worker MI->readsRegister(SplatReg, TRI))) {
142*9880d681SAndroid Build Coastguard Worker SI = Splats.erase(SI);
143*9880d681SAndroid Build Coastguard Worker continue;
144*9880d681SAndroid Build Coastguard Worker }
145*9880d681SAndroid Build Coastguard Worker
146*9880d681SAndroid Build Coastguard Worker ++SI;
147*9880d681SAndroid Build Coastguard Worker }
148*9880d681SAndroid Build Coastguard Worker
149*9880d681SAndroid Build Coastguard Worker if (MI->getOpcode() != PPC::QVESPLATI &&
150*9880d681SAndroid Build Coastguard Worker MI->getOpcode() != PPC::QVESPLATIs &&
151*9880d681SAndroid Build Coastguard Worker MI->getOpcode() != PPC::QVESPLATIb)
152*9880d681SAndroid Build Coastguard Worker continue;
153*9880d681SAndroid Build Coastguard Worker if (MI->getOperand(2).getImm() != 0)
154*9880d681SAndroid Build Coastguard Worker continue;
155*9880d681SAndroid Build Coastguard Worker
156*9880d681SAndroid Build Coastguard Worker // If there are other uses of the scalar value after this, replacing
157*9880d681SAndroid Build Coastguard Worker // those uses might be non-trivial.
158*9880d681SAndroid Build Coastguard Worker if (!MI->getOperand(1).isKill())
159*9880d681SAndroid Build Coastguard Worker continue;
160*9880d681SAndroid Build Coastguard Worker
161*9880d681SAndroid Build Coastguard Worker Splats.push_back(MI);
162*9880d681SAndroid Build Coastguard Worker }
163*9880d681SAndroid Build Coastguard Worker }
164*9880d681SAndroid Build Coastguard Worker
165*9880d681SAndroid Build Coastguard Worker return MadeChange;
166*9880d681SAndroid Build Coastguard Worker }
167