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