LLVM: lib/Target/PowerPC/PPCVSXFMAMutate.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
33
34using namespace llvm;
35
36
37
38
39
41 "disable-ppc-vsx-fma-mutation",
42 cl::desc("Disable VSX FMA instruction mutation"), cl::init(true),
44
45#define DEBUG_TYPE "ppc-vsx-fma-mutate"
46
47namespace llvm { namespace PPC {
49} }
50
51namespace {
52
53
54
56 static char ID;
58
59 LiveIntervals *LIS;
60 const PPCInstrInfo *TII;
61
62protected:
63 bool processBlock(MachineBasicBlock &MBB) {
65
67 const TargetRegisterInfo *TRI = &TII->getRegisterInfo();
71
72
73
74
75
76
77
79 if (AltOpc == -1)
80 continue;
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101 SlotIndex FMAIdx = LIS->getInstructionIndex(MI);
102
103 VNInfo *AddendValNo =
104 LIS->getInterval(MI.getOperand(1).getReg()).Query(FMAIdx).valueIn();
105
106
107 if (!AddendValNo)
108 continue;
109
110 MachineInstr *AddendMI = LIS->getInstructionFromIndex(AddendValNo->def);
111
112
113
114 if (!AddendMI || AddendMI->getParent() != MI.getParent())
115 continue;
116
117
118
120 continue;
121
125 MRI.getRegClass(AddendSrcReg))
126 continue;
127 } else {
128
129
131 ->contains(AddendSrcReg))
132 continue;
133 }
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153 bool OtherUsers = false, KillsAddendSrc = false;
155 J != JE; --J) {
156 if (J->readsVirtualRegister(AddendMI->getOperand(0).getReg())) {
157 OtherUsers = true;
158 break;
159 }
160 if (J->modifiesRegister(AddendSrcReg, TRI) ||
161 J->killsRegister(AddendSrcReg, TRI)) {
162 KillsAddendSrc = true;
163 break;
164 }
165 }
166
167 if (OtherUsers || KillsAddendSrc)
168 continue;
169
170
171
172
173
174
175
176
177
178 Register OldFMAReg = MI.getOperand(0).getReg();
179
180
181 unsigned KilledProdOp = 0, OtherProdOp = 0;
182 Register Reg2 = MI.getOperand(2).getReg();
183 Register Reg3 = MI.getOperand(3).getReg();
184 if (LIS->getInterval(Reg2).Query(FMAIdx).isKill()
185 && Reg2 != OldFMAReg) {
186 KilledProdOp = 2;
187 OtherProdOp = 3;
188 } else if (LIS->getInterval(Reg3).Query(FMAIdx).isKill()
189 && Reg3 != OldFMAReg) {
190 KilledProdOp = 3;
191 OtherProdOp = 2;
192 }
193
194
195
196 if (!KilledProdOp)
197 continue;
198
199
200
201
202
203
205 !LIS->getInterval(AddendSrcReg).liveAt(FMAIdx))
206 continue;
207
208
209
210 Register KilledProdReg = MI.getOperand(KilledProdOp).getReg();
211 Register OtherProdReg = MI.getOperand(OtherProdOp).getReg();
212
214 unsigned KilledProdSubReg = MI.getOperand(KilledProdOp).getSubReg();
215 unsigned OtherProdSubReg = MI.getOperand(OtherProdOp).getSubReg();
216
218 bool KilledProdRegKill = MI.getOperand(KilledProdOp).isKill();
219 bool OtherProdRegKill = MI.getOperand(OtherProdOp).isKill();
220
222 bool KilledProdRegUndef = MI.getOperand(KilledProdOp).isUndef();
223 bool OtherProdRegUndef = MI.getOperand(OtherProdOp).isUndef();
224
225
226
227
228
229 if (.constrainRegClass(KilledProdReg,
230 MRI.getRegClass(OldFMAReg)))
231 continue;
232
234 "Addend copy not tied to old FMA output!");
235
237
238 MI.getOperand(0).setReg(KilledProdReg);
239 MI.getOperand(1).setReg(KilledProdReg);
240 MI.getOperand(3).setReg(AddendSrcReg);
241
242 MI.getOperand(0).setSubReg(KilledProdSubReg);
243 MI.getOperand(1).setSubReg(KilledProdSubReg);
245
246 MI.getOperand(1).setIsKill(KilledProdRegKill);
247 MI.getOperand(3).setIsKill(AddRegKill);
248
249 MI.getOperand(1).setIsUndef(KilledProdRegUndef);
250 MI.getOperand(3).setIsUndef(AddRegUndef);
251
252 MI.setDesc(TII->get(AltOpc));
253
254
255
257 MI.getOperand(2).setReg(AddendSrcReg);
259 MI.getOperand(2).setIsKill(AddRegKill);
260 MI.getOperand(2).setIsUndef(AddRegUndef);
261 } else {
262 MI.getOperand(2).setReg(OtherProdReg);
263 MI.getOperand(2).setSubReg(OtherProdSubReg);
264 MI.getOperand(2).setIsKill(OtherProdRegKill);
265 MI.getOperand(2).setIsUndef(OtherProdRegUndef);
266 }
267
269
270
271
272
273 LiveInterval &FMAInt = LIS->getInterval(OldFMAReg);
275 for (auto UI = MRI.reg_nodbg_begin(OldFMAReg), UE = MRI.reg_nodbg_end();
276 UI != UE;) {
277 MachineOperand &UseMO = *UI;
279 ++UI;
280
281
282 if (UseMI == AddendMI)
283 continue;
284
285 UseMO.substVirtReg(KilledProdReg, KilledProdSubReg, *TRI);
286 }
287
288
289 LIS->removeInterval(KilledProdReg);
290 LiveInterval &NewFMAInt =
291 LIS->createAndComputeVirtRegInterval(KilledProdReg);
292
293 LLVM_DEBUG(dbgs() << " extended: " << NewFMAInt << '\n');
294 (void)NewFMAInt;
295
296
297
298
300 for (MCRegUnit Unit : TRI->regunits(AddendSrcReg.asMCReg())) {
301 LiveRange &AddendSrcRange = LIS->getRegUnit(Unit);
304 LLVM_DEBUG(dbgs() << " extended: " << AddendSrcRange << '\n');
305 }
306
308 LLVM_DEBUG(dbgs() << " trimmed: " << FMAInt << '\n');
309
310
311
312 LLVM_DEBUG(dbgs() << " removing: " << *AddendMI << '\n');
313 LIS->RemoveMachineInstrFromMaps(*AddendMI);
315
317 }
318
320 }
321
322public:
323 bool runOnMachineFunction(MachineFunction &MF) override {
325 return false;
326
327
328
329 const PPCSubtarget &STI = MF.getSubtarget();
330 if (!STI.hasVSX())
331 return false;
332
333 LIS = &getAnalysis().getLIS();
334
336
338
341
343 if (processBlock(B))
345
347 }
348
349 void getAnalysisUsage(AnalysisUsage &AU) const override {
350 AU.addRequired();
352 AU.addRequired();
354 AU.addRequired();
355 AU.addPreserved();
357 }
358 };
359}
360
362 "PowerPC VSX FMA Mutation", false, false)
368
370
371char PPCVSXFMAMutate::ID = 0;
373 return new PPCVSXFMAMutate();
374}
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
static const MachineInstrBuilder & AddSubReg(const MachineInstrBuilder &MIB, MCRegister Reg, unsigned SubIdx, unsigned State, const TargetRegisterInfo *TRI)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static cl::opt< bool > DisableVSXFMAMutate("disable-ppc-vsx-fma-mutation", cl::desc("Disable VSX FMA instruction mutation"), cl::init(true), cl::Hidden)
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
SI Optimize VGPR LiveRange
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
AnalysisUsage & addRequired()
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.
LLVM_ABI void removeValNo(VNInfo *ValNo)
removeValNo - Remove all the segments defined by the specified value#.
LLVM_ABI std::pair< VNInfo *, bool > extendInBlock(ArrayRef< SlotIndex > Undefs, SlotIndex StartIdx, SlotIndex Kill)
Attempt to extend a value defined after StartIdx to include Use.
VNInfo * getVNInfoAt(SlotIndex Idx) const
getVNInfoAt - Return the VNInfo that is live at Idx, or NULL.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
Analysis pass which computes a MachineDominatorTree.
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.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineBasicBlock * getParent() const
LLVM_ABI void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
unsigned getSubReg() const
LLVM_ABI void substVirtReg(Register Reg, unsigned SubIdx, const TargetRegisterInfo &)
substVirtReg - Substitute the current register with the virtual subregister Reg:SubReg.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
Register getReg() const
getReg - Returns the register number.
const PPCInstrInfo * getInstrInfo() const override
MCRegister asMCReg() const
Utility to check-convert this value to a MCRegister.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
SlotIndex getRegSlot(bool EC=false) const
Returns the register use/def slot in the current instruction for a normal or early-clobber def.
SlotIndex def
The index of the defining instruction.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Define some predicates that are used for node matching.
int getAltVSXFMAOpcode(uint16_t Opcode)
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
FunctionPass * createPPCVSXFMAMutatePass()
Definition PPCVSXFMAMutate.cpp:372
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...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
char & PPCVSXFMAMutateID
Definition PPCVSXFMAMutate.cpp:369