blob: ca6a0dc3c2a3ab0ec3e21e4d3739b02fc2287b69 [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 Dewhurst2c3cdd62016-10-19 14:01:06 +000019#include "llvm/IR/DiagnosticInfo.h"
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000020#include "llvm/IR/LLVMContext.h"
21#include "llvm/Support/raw_ostream.h"
Benjamin Kramer797fb962016-05-27 10:06:27 +000022using namespace llvm;
Chris Dewhurst4f7cac32016-05-23 10:56:36 +000023
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000024LEONMachineFunctionPass::LEONMachineFunctionPass(char &ID)
25 : MachineFunctionPass(ID) {}
Chris Dewhurst4f7cac32016-05-23 10:56:36 +000026
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000027int LEONMachineFunctionPass::GetRegIndexForOperand(MachineInstr &MI,
28 int OperandIndex) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +000029 if (MI.getNumOperands() > 0) {
30 if (OperandIndex == LAST_OPERAND) {
31 OperandIndex = MI.getNumOperands() - 1;
32 }
33
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000034 if (MI.getNumOperands() > (unsigned)OperandIndex &&
Chris Dewhurst0c1e0022016-06-19 11:03:28 +000035 MI.getOperand(OperandIndex).isReg()) {
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000036 return (int)MI.getOperand(OperandIndex).getReg();
Chris Dewhurst0c1e0022016-06-19 11:03:28 +000037 }
38 }
39
40 static int NotFoundIndex = -10;
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000041 // Return a different number each time to avoid any comparisons between the
42 // values returned.
Chris Dewhurst0c1e0022016-06-19 11:03:28 +000043 NotFoundIndex -= 10;
44 return NotFoundIndex;
45}
46
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000047// finds a new free FP register
48// checks also the AllocatedRegisters vector
49int LEONMachineFunctionPass::getUnusedFPRegister(MachineRegisterInfo &MRI) {
50 for (int RegisterIndex = SP::F0; RegisterIndex <= SP::F31; ++RegisterIndex) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +000051 if (!MRI.isPhysRegUsed(RegisterIndex) &&
David Majnemer0d955d02016-08-11 22:21:41 +000052 !is_contained(UsedRegisters, RegisterIndex)) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +000053 return RegisterIndex;
54 }
55 }
56
57 return -1;
58}
59
Chris Dewhurst4f7cac32016-05-23 10:56:36 +000060//*****************************************************************************
61//**** InsertNOPLoad pass
62//*****************************************************************************
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000063// This pass fixes the incorrectly working Load instructions that exists for
64// some earlier versions of the LEON processor line. NOP instructions must
65// be inserted after the load instruction to ensure that the Load instruction
66// behaves as expected for these processors.
67//
68// This pass inserts a NOP after any LD or LDF instruction.
Chris Dewhurst4f7cac32016-05-23 10:56:36 +000069//
70char InsertNOPLoad::ID = 0;
71
Francis Visoiu Mistrih8b617642017-05-18 17:21:13 +000072InsertNOPLoad::InsertNOPLoad() : LEONMachineFunctionPass(ID) {}
Chris Dewhurst4f7cac32016-05-23 10:56:36 +000073
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000074bool InsertNOPLoad::runOnMachineFunction(MachineFunction &MF) {
Chris Dewhurst4f7cac32016-05-23 10:56:36 +000075 Subtarget = &MF.getSubtarget<SparcSubtarget>();
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000076 const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
Chris Dewhurst4f7cac32016-05-23 10:56:36 +000077 DebugLoc DL = DebugLoc();
78
79 bool Modified = false;
80 for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
81 MachineBasicBlock &MBB = *MFI;
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000082 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
Chris Dewhurst4f7cac32016-05-23 10:56:36 +000083 MachineInstr &MI = *MBBI;
84 unsigned Opcode = MI.getOpcode();
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000085 if (Opcode >= SP::LDDArr && Opcode <= SP::LDrr) {
Chris Dewhurst4f7cac32016-05-23 10:56:36 +000086 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
87 BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP));
88 Modified = true;
Chris Dewhurst4f7cac32016-05-23 10:56:36 +000089 }
90 }
91 }
92
93 return Modified;
94}
Chris Dewhurst0c1e0022016-06-19 11:03:28 +000095
96//*****************************************************************************
97//**** FixFSMULD pass
98//*****************************************************************************
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000099// This pass fixes the incorrectly working FSMULD instruction that exists for
100// some earlier versions of the LEON processor line.
101//
102// The pass should convert the FSMULD operands to double precision in scratch
103// registers, then calculate the result with the FMULD instruction. Therefore,
104// the pass should replace operations of the form:
105// fsmuld %f20,%f21,%f8
106// with the sequence:
107// fstod %f20,%f0
108// fstod %f21,%f2
109// fmuld %f0,%f2,%f8
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000110//
111char FixFSMULD::ID = 0;
112
Francis Visoiu Mistrih8b617642017-05-18 17:21:13 +0000113FixFSMULD::FixFSMULD() : LEONMachineFunctionPass(ID) {}
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000114
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000115bool FixFSMULD::runOnMachineFunction(MachineFunction &MF) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000116 Subtarget = &MF.getSubtarget<SparcSubtarget>();
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000117 const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000118 DebugLoc DL = DebugLoc();
119
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000120 bool Modified = false;
121 for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
122 MachineBasicBlock &MBB = *MFI;
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000123 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000124
125 MachineInstr &MI = *MBBI;
126 unsigned Opcode = MI.getOpcode();
127
128 const int UNASSIGNED_INDEX = -1;
129 int Reg1Index = UNASSIGNED_INDEX;
130 int Reg2Index = UNASSIGNED_INDEX;
131 int Reg3Index = UNASSIGNED_INDEX;
132
133 if (Opcode == SP::FSMULD && MI.getNumOperands() == 3) {
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000134 // take the registers from fsmuld %f20,%f21,%f8
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000135 Reg1Index = MI.getOperand(0).getReg();
136 Reg2Index = MI.getOperand(1).getReg();
137 Reg3Index = MI.getOperand(2).getReg();
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000138 }
139
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000140 if (Reg1Index != UNASSIGNED_INDEX && Reg2Index != UNASSIGNED_INDEX &&
141 Reg3Index != UNASSIGNED_INDEX) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000142 clearUsedRegisterList();
143 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000144 // Whatever Reg3Index is hasn't been used yet, so we need to reserve it.
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000145 markRegisterUsed(Reg3Index);
146 const int ScratchReg1Index = getUnusedFPRegister(MF.getRegInfo());
147 markRegisterUsed(ScratchReg1Index);
148 const int ScratchReg2Index = getUnusedFPRegister(MF.getRegInfo());
149 markRegisterUsed(ScratchReg2Index);
150
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000151 if (ScratchReg1Index == UNASSIGNED_INDEX ||
152 ScratchReg2Index == UNASSIGNED_INDEX) {
153 errs() << "Cannot allocate free scratch registers for the FixFSMULD "
154 "pass."
155 << "\n";
156 } else {
157 // create fstod %f20,%f0
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000158 BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD))
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000159 .addReg(ScratchReg1Index)
160 .addReg(Reg1Index);
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000161
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000162 // create fstod %f21,%f2
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000163 BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD))
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000164 .addReg(ScratchReg2Index)
165 .addReg(Reg2Index);
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000166
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000167 // create fmuld %f0,%f2,%f8
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000168 BuildMI(MBB, MBBI, DL, TII.get(SP::FMULD))
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000169 .addReg(Reg3Index)
170 .addReg(ScratchReg1Index)
171 .addReg(ScratchReg2Index);
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000172
173 MI.eraseFromParent();
174 MBBI = NMBBI;
175
176 Modified = true;
177 }
178 }
179 }
180 }
181
182 return Modified;
183}
184
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000185//*****************************************************************************
186//**** ReplaceFMULS pass
187//*****************************************************************************
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000188// This pass fixes the incorrectly working FMULS instruction that exists for
189// some earlier versions of the LEON processor line.
190//
191// This pass converts the FMULS operands to double precision in scratch
192// registers, then calculates the result with the FMULD instruction.
193// The pass should replace operations of the form:
194// fmuls %f20,%f21,%f8
195// with the sequence:
196// fstod %f20,%f0
197// fstod %f21,%f2
198// fmuld %f0,%f2,%f8
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000199//
200char ReplaceFMULS::ID = 0;
201
Francis Visoiu Mistrih8b617642017-05-18 17:21:13 +0000202ReplaceFMULS::ReplaceFMULS() : LEONMachineFunctionPass(ID) {}
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000203
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000204bool ReplaceFMULS::runOnMachineFunction(MachineFunction &MF) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000205 Subtarget = &MF.getSubtarget<SparcSubtarget>();
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000206 const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000207 DebugLoc DL = DebugLoc();
208
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000209 bool Modified = false;
210 for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
211 MachineBasicBlock &MBB = *MFI;
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000212 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000213 MachineInstr &MI = *MBBI;
214 unsigned Opcode = MI.getOpcode();
215
216 const int UNASSIGNED_INDEX = -1;
217 int Reg1Index = UNASSIGNED_INDEX;
218 int Reg2Index = UNASSIGNED_INDEX;
219 int Reg3Index = UNASSIGNED_INDEX;
220
221 if (Opcode == SP::FMULS && MI.getNumOperands() == 3) {
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000222 // take the registers from fmuls %f20,%f21,%f8
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000223 Reg1Index = MI.getOperand(0).getReg();
224 Reg2Index = MI.getOperand(1).getReg();
225 Reg3Index = MI.getOperand(2).getReg();
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000226 }
227
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000228 if (Reg1Index != UNASSIGNED_INDEX && Reg2Index != UNASSIGNED_INDEX &&
229 Reg3Index != UNASSIGNED_INDEX) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000230 clearUsedRegisterList();
231 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000232 // Whatever Reg3Index is hasn't been used yet, so we need to reserve it.
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000233 markRegisterUsed(Reg3Index);
234 const int ScratchReg1Index = getUnusedFPRegister(MF.getRegInfo());
235 markRegisterUsed(ScratchReg1Index);
236 const int ScratchReg2Index = getUnusedFPRegister(MF.getRegInfo());
237 markRegisterUsed(ScratchReg2Index);
238
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000239 if (ScratchReg1Index == UNASSIGNED_INDEX ||
240 ScratchReg2Index == UNASSIGNED_INDEX) {
241 errs() << "Cannot allocate free scratch registers for the "
242 "ReplaceFMULS pass."
243 << "\n";
244 } else {
245 // create fstod %f20,%f0
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000246 BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD))
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000247 .addReg(ScratchReg1Index)
248 .addReg(Reg1Index);
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000249
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000250 // create fstod %f21,%f2
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000251 BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD))
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000252 .addReg(ScratchReg2Index)
253 .addReg(Reg2Index);
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000254
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000255 // create fmuld %f0,%f2,%f8
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000256 BuildMI(MBB, MBBI, DL, TII.get(SP::FMULD))
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000257 .addReg(Reg3Index)
258 .addReg(ScratchReg1Index)
259 .addReg(ScratchReg2Index);
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000260
261 MI.eraseFromParent();
262 MBBI = NMBBI;
263
264 Modified = true;
265 }
266 }
267 }
268 }
269
270 return Modified;
271}
272
Chris Dewhurst2c3cdd62016-10-19 14:01:06 +0000273
274//*****************************************************************************
275//**** DetectRoundChange pass
276//*****************************************************************************
277// To prevent any explicit change of the default rounding mode, this pass
278// detects any call of the fesetround function.
279// A warning is generated to ensure the user knows this has happened.
280//
281// Detects an erratum in UT699 LEON 3 processor
282
283char DetectRoundChange::ID = 0;
284
Francis Visoiu Mistrih8b617642017-05-18 17:21:13 +0000285DetectRoundChange::DetectRoundChange() : LEONMachineFunctionPass(ID) {}
Chris Dewhurst2c3cdd62016-10-19 14:01:06 +0000286
287bool DetectRoundChange::runOnMachineFunction(MachineFunction &MF) {
288 Subtarget = &MF.getSubtarget<SparcSubtarget>();
289
290 bool Modified = false;
291 for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
292 MachineBasicBlock &MBB = *MFI;
293 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
294 MachineInstr &MI = *MBBI;
295 unsigned Opcode = MI.getOpcode();
296 if (Opcode == SP::CALL && MI.getNumOperands() > 0) {
297 MachineOperand &MO = MI.getOperand(0);
298
299 if (MO.isGlobal()) {
300 StringRef FuncName = MO.getGlobal()->getName();
301 if (FuncName.compare_lower("fesetround") == 0) {
302 errs() << "Error: You are using the detectroundchange "
303 "option to detect rounding changes that will "
304 "cause LEON errata. The only way to fix this "
305 "is to remove the call to fesetround from "
306 "the source code.\n";
307 }
308 }
309 }
310 }
311 }
312
313 return Modified;
314}
315
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000316//*****************************************************************************
317//**** FixAllFDIVSQRT pass
318//*****************************************************************************
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000319// This pass fixes the incorrectly working FDIVx and FSQRTx instructions that
320// exist for some earlier versions of the LEON processor line. Five NOP
321// instructions need to be inserted after these instructions to ensure the
322// correct result is placed in the destination registers before they are used.
323//
324// This pass implements two fixes:
325// 1) fixing the FSQRTS and FSQRTD instructions.
326// 2) fixing the FDIVS and FDIVD instructions.
327//
328// FSQRTS and FDIVS are converted to FDIVD and FSQRTD respectively earlier in
329// the pipeline when this option is enabled, so this pass needs only to deal
330// with the changes that still need implementing for the "double" versions
331// of these instructions.
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000332//
333char FixAllFDIVSQRT::ID = 0;
334
Francis Visoiu Mistrih8b617642017-05-18 17:21:13 +0000335FixAllFDIVSQRT::FixAllFDIVSQRT() : LEONMachineFunctionPass(ID) {}
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000336
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000337bool FixAllFDIVSQRT::runOnMachineFunction(MachineFunction &MF) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000338 Subtarget = &MF.getSubtarget<SparcSubtarget>();
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000339 const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000340 DebugLoc DL = DebugLoc();
341
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000342 bool Modified = false;
343 for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
344 MachineBasicBlock &MBB = *MFI;
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000345 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000346 MachineInstr &MI = *MBBI;
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000347 unsigned Opcode = MI.getOpcode();
348
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000349 // Note: FDIVS and FSQRTS cannot be generated when this erratum fix is
350 // switched on so we don't need to check for them here. They will
351 // already have been converted to FSQRTD or FDIVD earlier in the
352 // pipeline.
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000353 if (Opcode == SP::FSQRTD || Opcode == SP::FDIVD) {
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000354 for (int InsertedCount = 0; InsertedCount < 5; InsertedCount++)
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000355 BuildMI(MBB, MBBI, DL, TII.get(SP::NOP));
356
357 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000358 for (int InsertedCount = 0; InsertedCount < 28; InsertedCount++)
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000359 BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP));
360
361 Modified = true;
362 }
363 }
364 }
365
366 return Modified;
367}