blob: c186cae316a290d835fb10e97f446a6bca807475 [file] [log] [blame]
Chris Dewhurst4f7cac32016-05-23 10:56:36 +00001//===------ LeonPasses.cpp - Define passes specific to LEON ---------------===//
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//
11//===----------------------------------------------------------------------===//
12
13#include "LeonPasses.h"
Chris Dewhurst4f7cac32016-05-23 10:56:36 +000014#include "llvm/CodeGen/ISDOpcodes.h"
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000015#include "llvm/CodeGen/MachineFunction.h"
Chris Dewhurst4f7cac32016-05-23 10:56:36 +000016#include "llvm/CodeGen/MachineInstr.h"
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000017#include "llvm/CodeGen/MachineInstrBuilder.h"
Chris Dewhurst4f7cac32016-05-23 10:56:36 +000018#include "llvm/CodeGen/MachineRegisterInfo.h"
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000019#include "llvm/IR/LLVMContext.h"
20#include "llvm/Support/raw_ostream.h"
Benjamin Kramer797fb962016-05-27 10:06:27 +000021using namespace llvm;
Chris Dewhurst4f7cac32016-05-23 10:56:36 +000022
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000023LEONMachineFunctionPass::LEONMachineFunctionPass(TargetMachine &tm, char &ID)
24 : MachineFunctionPass(ID) {}
Chris Dewhurst4f7cac32016-05-23 10:56:36 +000025
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000026LEONMachineFunctionPass::LEONMachineFunctionPass(char &ID)
27 : MachineFunctionPass(ID) {}
Chris Dewhurst4f7cac32016-05-23 10:56:36 +000028
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000029int LEONMachineFunctionPass::GetRegIndexForOperand(MachineInstr &MI,
30 int OperandIndex) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +000031 if (MI.getNumOperands() > 0) {
32 if (OperandIndex == LAST_OPERAND) {
33 OperandIndex = MI.getNumOperands() - 1;
34 }
35
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000036 if (MI.getNumOperands() > (unsigned)OperandIndex &&
Chris Dewhurst0c1e0022016-06-19 11:03:28 +000037 MI.getOperand(OperandIndex).isReg()) {
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000038 return (int)MI.getOperand(OperandIndex).getReg();
Chris Dewhurst0c1e0022016-06-19 11:03:28 +000039 }
40 }
41
42 static int NotFoundIndex = -10;
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000043 // Return a different number each time to avoid any comparisons between the
44 // values returned.
Chris Dewhurst0c1e0022016-06-19 11:03:28 +000045 NotFoundIndex -= 10;
46 return NotFoundIndex;
47}
48
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000049// finds a new free FP register
50// checks also the AllocatedRegisters vector
51int LEONMachineFunctionPass::getUnusedFPRegister(MachineRegisterInfo &MRI) {
52 for (int RegisterIndex = SP::F0; RegisterIndex <= SP::F31; ++RegisterIndex) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +000053 if (!MRI.isPhysRegUsed(RegisterIndex) &&
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000054 !(std::find(UsedRegisters.begin(), UsedRegisters.end(),
55 RegisterIndex) != UsedRegisters.end())) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +000056 return RegisterIndex;
57 }
58 }
59
60 return -1;
61}
62
Chris Dewhurst4f7cac32016-05-23 10:56:36 +000063//*****************************************************************************
64//**** InsertNOPLoad pass
65//*****************************************************************************
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000066// This pass fixes the incorrectly working Load instructions that exists for
67// some earlier versions of the LEON processor line. NOP instructions must
68// be inserted after the load instruction to ensure that the Load instruction
69// behaves as expected for these processors.
70//
71// This pass inserts a NOP after any LD or LDF instruction.
Chris Dewhurst4f7cac32016-05-23 10:56:36 +000072//
73char InsertNOPLoad::ID = 0;
74
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000075InsertNOPLoad::InsertNOPLoad(TargetMachine &tm)
76 : LEONMachineFunctionPass(tm, ID) {}
Chris Dewhurst4f7cac32016-05-23 10:56:36 +000077
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000078bool InsertNOPLoad::runOnMachineFunction(MachineFunction &MF) {
Chris Dewhurst4f7cac32016-05-23 10:56:36 +000079 Subtarget = &MF.getSubtarget<SparcSubtarget>();
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000080 const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
Chris Dewhurst4f7cac32016-05-23 10:56:36 +000081 DebugLoc DL = DebugLoc();
82
83 bool Modified = false;
84 for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
85 MachineBasicBlock &MBB = *MFI;
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000086 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
Chris Dewhurst4f7cac32016-05-23 10:56:36 +000087 MachineInstr &MI = *MBBI;
88 unsigned Opcode = MI.getOpcode();
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000089 if (Opcode >= SP::LDDArr && Opcode <= SP::LDrr) {
Chris Dewhurst4f7cac32016-05-23 10:56:36 +000090 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
91 BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP));
92 Modified = true;
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000093 } else if (MI.isInlineAsm()) {
Benjamin Kramer1cda54f2016-05-27 16:45:37 +000094 // Look for an inline ld or ldf instruction.
95 StringRef AsmString =
96 MI.getOperand(InlineAsm::MIOp_AsmString).getSymbolName();
97 if (AsmString.startswith_lower("ld")) {
Chris Dewhurst4f7cac32016-05-23 10:56:36 +000098 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
99 BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP));
100 Modified = true;
101 }
102 }
103 }
104 }
105
106 return Modified;
107}
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000108
109//*****************************************************************************
110//**** FixFSMULD pass
111//*****************************************************************************
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000112// This pass fixes the incorrectly working FSMULD instruction that exists for
113// some earlier versions of the LEON processor line.
114//
115// The pass should convert the FSMULD operands to double precision in scratch
116// registers, then calculate the result with the FMULD instruction. Therefore,
117// the pass should replace operations of the form:
118// fsmuld %f20,%f21,%f8
119// with the sequence:
120// fstod %f20,%f0
121// fstod %f21,%f2
122// fmuld %f0,%f2,%f8
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000123//
124char FixFSMULD::ID = 0;
125
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000126FixFSMULD::FixFSMULD(TargetMachine &tm) : LEONMachineFunctionPass(tm, ID) {}
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000127
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000128bool FixFSMULD::runOnMachineFunction(MachineFunction &MF) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000129 Subtarget = &MF.getSubtarget<SparcSubtarget>();
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000130 const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000131 DebugLoc DL = DebugLoc();
132
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000133 bool Modified = false;
134 for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
135 MachineBasicBlock &MBB = *MFI;
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000136 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000137
138 MachineInstr &MI = *MBBI;
139 unsigned Opcode = MI.getOpcode();
140
141 const int UNASSIGNED_INDEX = -1;
142 int Reg1Index = UNASSIGNED_INDEX;
143 int Reg2Index = UNASSIGNED_INDEX;
144 int Reg3Index = UNASSIGNED_INDEX;
145
146 if (Opcode == SP::FSMULD && MI.getNumOperands() == 3) {
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000147 // take the registers from fsmuld %f20,%f21,%f8
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000148 Reg1Index = MI.getOperand(0).getReg();
149 Reg2Index = MI.getOperand(1).getReg();
150 Reg3Index = MI.getOperand(2).getReg();
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000151 } else if (MI.isInlineAsm()) {
152 std::string AsmString(
Benjamin Kramer020a7402016-06-27 09:38:56 +0000153 MI.getOperand(InlineAsm::MIOp_AsmString).getSymbolName());
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000154 std::string FMULSOpCoode("fsmuld");
155 std::transform(AsmString.begin(), AsmString.end(), AsmString.begin(),
156 ::tolower);
157 if (AsmString.find(FMULSOpCoode) ==
158 0) { // this is an inline FSMULD instruction
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000159
160 unsigned StartOp = InlineAsm::MIOp_FirstOperand;
161
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000162 // extracts the registers from the inline assembly instruction
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000163 for (unsigned i = StartOp, e = MI.getNumOperands(); i != e; ++i) {
164 const MachineOperand &MO = MI.getOperand(i);
165 if (MO.isReg()) {
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000166 if (Reg1Index == UNASSIGNED_INDEX)
167 Reg1Index = MO.getReg();
168 else if (Reg2Index == UNASSIGNED_INDEX)
169 Reg2Index = MO.getReg();
170 else if (Reg3Index == UNASSIGNED_INDEX)
171 Reg3Index = MO.getReg();
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000172 }
173 if (Reg3Index != UNASSIGNED_INDEX)
174 break;
175 }
176 }
177 }
178
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000179 if (Reg1Index != UNASSIGNED_INDEX && Reg2Index != UNASSIGNED_INDEX &&
180 Reg3Index != UNASSIGNED_INDEX) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000181 clearUsedRegisterList();
182 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000183 // Whatever Reg3Index is hasn't been used yet, so we need to reserve it.
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000184 markRegisterUsed(Reg3Index);
185 const int ScratchReg1Index = getUnusedFPRegister(MF.getRegInfo());
186 markRegisterUsed(ScratchReg1Index);
187 const int ScratchReg2Index = getUnusedFPRegister(MF.getRegInfo());
188 markRegisterUsed(ScratchReg2Index);
189
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000190 if (ScratchReg1Index == UNASSIGNED_INDEX ||
191 ScratchReg2Index == UNASSIGNED_INDEX) {
192 errs() << "Cannot allocate free scratch registers for the FixFSMULD "
193 "pass."
194 << "\n";
195 } else {
196 // create fstod %f20,%f0
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000197 BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD))
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000198 .addReg(ScratchReg1Index)
199 .addReg(Reg1Index);
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000200
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000201 // create fstod %f21,%f2
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000202 BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD))
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000203 .addReg(ScratchReg2Index)
204 .addReg(Reg2Index);
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000205
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000206 // create fmuld %f0,%f2,%f8
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000207 BuildMI(MBB, MBBI, DL, TII.get(SP::FMULD))
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000208 .addReg(Reg3Index)
209 .addReg(ScratchReg1Index)
210 .addReg(ScratchReg2Index);
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000211
212 MI.eraseFromParent();
213 MBBI = NMBBI;
214
215 Modified = true;
216 }
217 }
218 }
219 }
220
221 return Modified;
222}
223
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000224//*****************************************************************************
225//**** ReplaceFMULS pass
226//*****************************************************************************
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000227// This pass fixes the incorrectly working FMULS instruction that exists for
228// some earlier versions of the LEON processor line.
229//
230// This pass converts the FMULS operands to double precision in scratch
231// registers, then calculates the result with the FMULD instruction.
232// The pass should replace operations of the form:
233// fmuls %f20,%f21,%f8
234// with the sequence:
235// fstod %f20,%f0
236// fstod %f21,%f2
237// fmuld %f0,%f2,%f8
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000238//
239char ReplaceFMULS::ID = 0;
240
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000241ReplaceFMULS::ReplaceFMULS(TargetMachine &tm)
242 : LEONMachineFunctionPass(tm, ID) {}
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000243
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000244bool ReplaceFMULS::runOnMachineFunction(MachineFunction &MF) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000245 Subtarget = &MF.getSubtarget<SparcSubtarget>();
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000246 const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000247 DebugLoc DL = DebugLoc();
248
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000249 bool Modified = false;
250 for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
251 MachineBasicBlock &MBB = *MFI;
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000252 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000253 MachineInstr &MI = *MBBI;
254 unsigned Opcode = MI.getOpcode();
255
256 const int UNASSIGNED_INDEX = -1;
257 int Reg1Index = UNASSIGNED_INDEX;
258 int Reg2Index = UNASSIGNED_INDEX;
259 int Reg3Index = UNASSIGNED_INDEX;
260
261 if (Opcode == SP::FMULS && MI.getNumOperands() == 3) {
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000262 // take the registers from fmuls %f20,%f21,%f8
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000263 Reg1Index = MI.getOperand(0).getReg();
264 Reg2Index = MI.getOperand(1).getReg();
265 Reg3Index = MI.getOperand(2).getReg();
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000266 } else if (MI.isInlineAsm()) {
267 std::string AsmString(
Benjamin Kramer020a7402016-06-27 09:38:56 +0000268 MI.getOperand(InlineAsm::MIOp_AsmString).getSymbolName());
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000269 std::string FMULSOpCoode("fmuls");
270 std::transform(AsmString.begin(), AsmString.end(), AsmString.begin(),
271 ::tolower);
272 if (AsmString.find(FMULSOpCoode) ==
273 0) { // this is an inline FMULS instruction
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000274 unsigned StartOp = InlineAsm::MIOp_FirstOperand;
275
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000276 // extracts the registers from the inline assembly instruction
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000277 for (unsigned i = StartOp, e = MI.getNumOperands(); i != e; ++i) {
278 const MachineOperand &MO = MI.getOperand(i);
279 if (MO.isReg()) {
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000280 if (Reg1Index == UNASSIGNED_INDEX)
281 Reg1Index = MO.getReg();
282 else if (Reg2Index == UNASSIGNED_INDEX)
283 Reg2Index = MO.getReg();
284 else if (Reg3Index == UNASSIGNED_INDEX)
285 Reg3Index = MO.getReg();
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000286 }
287 if (Reg3Index != UNASSIGNED_INDEX)
288 break;
289 }
290 }
291 }
292
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000293 if (Reg1Index != UNASSIGNED_INDEX && Reg2Index != UNASSIGNED_INDEX &&
294 Reg3Index != UNASSIGNED_INDEX) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000295 clearUsedRegisterList();
296 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000297 // Whatever Reg3Index is hasn't been used yet, so we need to reserve it.
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000298 markRegisterUsed(Reg3Index);
299 const int ScratchReg1Index = getUnusedFPRegister(MF.getRegInfo());
300 markRegisterUsed(ScratchReg1Index);
301 const int ScratchReg2Index = getUnusedFPRegister(MF.getRegInfo());
302 markRegisterUsed(ScratchReg2Index);
303
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000304 if (ScratchReg1Index == UNASSIGNED_INDEX ||
305 ScratchReg2Index == UNASSIGNED_INDEX) {
306 errs() << "Cannot allocate free scratch registers for the "
307 "ReplaceFMULS pass."
308 << "\n";
309 } else {
310 // create fstod %f20,%f0
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000311 BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD))
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000312 .addReg(ScratchReg1Index)
313 .addReg(Reg1Index);
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000314
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000315 // create fstod %f21,%f2
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000316 BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD))
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000317 .addReg(ScratchReg2Index)
318 .addReg(Reg2Index);
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000319
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000320 // create fmuld %f0,%f2,%f8
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000321 BuildMI(MBB, MBBI, DL, TII.get(SP::FMULD))
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000322 .addReg(Reg3Index)
323 .addReg(ScratchReg1Index)
324 .addReg(ScratchReg2Index);
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000325
326 MI.eraseFromParent();
327 MBBI = NMBBI;
328
329 Modified = true;
330 }
331 }
332 }
333 }
334
335 return Modified;
336}
337
338//*****************************************************************************
339//**** FixAllFDIVSQRT pass
340//*****************************************************************************
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000341// This pass fixes the incorrectly working FDIVx and FSQRTx instructions that
342// exist for some earlier versions of the LEON processor line. Five NOP
343// instructions need to be inserted after these instructions to ensure the
344// correct result is placed in the destination registers before they are used.
345//
346// This pass implements two fixes:
347// 1) fixing the FSQRTS and FSQRTD instructions.
348// 2) fixing the FDIVS and FDIVD instructions.
349//
350// FSQRTS and FDIVS are converted to FDIVD and FSQRTD respectively earlier in
351// the pipeline when this option is enabled, so this pass needs only to deal
352// with the changes that still need implementing for the "double" versions
353// of these instructions.
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000354//
355char FixAllFDIVSQRT::ID = 0;
356
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000357FixAllFDIVSQRT::FixAllFDIVSQRT(TargetMachine &tm)
358 : LEONMachineFunctionPass(tm, ID) {}
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000359
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000360bool FixAllFDIVSQRT::runOnMachineFunction(MachineFunction &MF) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000361 Subtarget = &MF.getSubtarget<SparcSubtarget>();
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000362 const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000363 DebugLoc DL = DebugLoc();
364
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000365 bool Modified = false;
366 for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
367 MachineBasicBlock &MBB = *MFI;
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000368 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000369 MachineInstr &MI = *MBBI;
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000370 unsigned Opcode = MI.getOpcode();
371
372 if (MI.isInlineAsm()) {
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000373 std::string AsmString(
Benjamin Kramer020a7402016-06-27 09:38:56 +0000374 MI.getOperand(InlineAsm::MIOp_AsmString).getSymbolName());
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000375 std::string FSQRTDOpCode("fsqrtd");
376 std::string FDIVDOpCode("fdivd");
377 std::transform(AsmString.begin(), AsmString.end(), AsmString.begin(),
378 ::tolower);
379 if (AsmString.find(FSQRTDOpCode) ==
380 0) { // this is an inline fsqrts instruction
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000381 Opcode = SP::FSQRTD;
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000382 } else if (AsmString.find(FDIVDOpCode) ==
383 0) { // this is an inline fsqrts instruction
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000384 Opcode = SP::FDIVD;
385 }
386 }
387
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000388 // Note: FDIVS and FSQRTS cannot be generated when this erratum fix is
389 // switched on so we don't need to check for them here. They will
390 // already have been converted to FSQRTD or FDIVD earlier in the
391 // pipeline.
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000392 if (Opcode == SP::FSQRTD || Opcode == SP::FDIVD) {
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000393 for (int InsertedCount = 0; InsertedCount < 5; InsertedCount++)
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000394 BuildMI(MBB, MBBI, DL, TII.get(SP::NOP));
395
396 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000397 for (int InsertedCount = 0; InsertedCount < 28; InsertedCount++)
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000398 BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP));
399
400 Modified = true;
401 }
402 }
403 }
404
405 return Modified;
406}