blob: 0acc2875daa848319049fec3b43d28d370015208 [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(TargetMachine &tm, char &ID)
25 : MachineFunctionPass(ID) {}
Chris Dewhurst4f7cac32016-05-23 10:56:36 +000026
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000027LEONMachineFunctionPass::LEONMachineFunctionPass(char &ID)
28 : MachineFunctionPass(ID) {}
Chris Dewhurst4f7cac32016-05-23 10:56:36 +000029
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000030int LEONMachineFunctionPass::GetRegIndexForOperand(MachineInstr &MI,
31 int OperandIndex) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +000032 if (MI.getNumOperands() > 0) {
33 if (OperandIndex == LAST_OPERAND) {
34 OperandIndex = MI.getNumOperands() - 1;
35 }
36
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000037 if (MI.getNumOperands() > (unsigned)OperandIndex &&
Chris Dewhurst0c1e0022016-06-19 11:03:28 +000038 MI.getOperand(OperandIndex).isReg()) {
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000039 return (int)MI.getOperand(OperandIndex).getReg();
Chris Dewhurst0c1e0022016-06-19 11:03:28 +000040 }
41 }
42
43 static int NotFoundIndex = -10;
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000044 // Return a different number each time to avoid any comparisons between the
45 // values returned.
Chris Dewhurst0c1e0022016-06-19 11:03:28 +000046 NotFoundIndex -= 10;
47 return NotFoundIndex;
48}
49
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000050// finds a new free FP register
51// checks also the AllocatedRegisters vector
52int LEONMachineFunctionPass::getUnusedFPRegister(MachineRegisterInfo &MRI) {
53 for (int RegisterIndex = SP::F0; RegisterIndex <= SP::F31; ++RegisterIndex) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +000054 if (!MRI.isPhysRegUsed(RegisterIndex) &&
David Majnemer0d955d02016-08-11 22:21:41 +000055 !is_contained(UsedRegisters, RegisterIndex)) {
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 Dewhurst4f7cac32016-05-23 10:56:36 +000093 }
94 }
95 }
96
97 return Modified;
98}
Chris Dewhurst0c1e0022016-06-19 11:03:28 +000099
100//*****************************************************************************
101//**** FixFSMULD pass
102//*****************************************************************************
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000103// This pass fixes the incorrectly working FSMULD instruction that exists for
104// some earlier versions of the LEON processor line.
105//
106// The pass should convert the FSMULD operands to double precision in scratch
107// registers, then calculate the result with the FMULD instruction. Therefore,
108// the pass should replace operations of the form:
109// fsmuld %f20,%f21,%f8
110// with the sequence:
111// fstod %f20,%f0
112// fstod %f21,%f2
113// fmuld %f0,%f2,%f8
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000114//
115char FixFSMULD::ID = 0;
116
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000117FixFSMULD::FixFSMULD(TargetMachine &tm) : LEONMachineFunctionPass(tm, ID) {}
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000118
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000119bool FixFSMULD::runOnMachineFunction(MachineFunction &MF) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000120 Subtarget = &MF.getSubtarget<SparcSubtarget>();
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000121 const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000122 DebugLoc DL = DebugLoc();
123
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000124 bool Modified = false;
125 for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
126 MachineBasicBlock &MBB = *MFI;
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000127 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000128
129 MachineInstr &MI = *MBBI;
130 unsigned Opcode = MI.getOpcode();
131
132 const int UNASSIGNED_INDEX = -1;
133 int Reg1Index = UNASSIGNED_INDEX;
134 int Reg2Index = UNASSIGNED_INDEX;
135 int Reg3Index = UNASSIGNED_INDEX;
136
137 if (Opcode == SP::FSMULD && MI.getNumOperands() == 3) {
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000138 // take the registers from fsmuld %f20,%f21,%f8
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000139 Reg1Index = MI.getOperand(0).getReg();
140 Reg2Index = MI.getOperand(1).getReg();
141 Reg3Index = MI.getOperand(2).getReg();
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000142 }
143
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000144 if (Reg1Index != UNASSIGNED_INDEX && Reg2Index != UNASSIGNED_INDEX &&
145 Reg3Index != UNASSIGNED_INDEX) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000146 clearUsedRegisterList();
147 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000148 // Whatever Reg3Index is hasn't been used yet, so we need to reserve it.
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000149 markRegisterUsed(Reg3Index);
150 const int ScratchReg1Index = getUnusedFPRegister(MF.getRegInfo());
151 markRegisterUsed(ScratchReg1Index);
152 const int ScratchReg2Index = getUnusedFPRegister(MF.getRegInfo());
153 markRegisterUsed(ScratchReg2Index);
154
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000155 if (ScratchReg1Index == UNASSIGNED_INDEX ||
156 ScratchReg2Index == UNASSIGNED_INDEX) {
157 errs() << "Cannot allocate free scratch registers for the FixFSMULD "
158 "pass."
159 << "\n";
160 } else {
161 // create fstod %f20,%f0
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000162 BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD))
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000163 .addReg(ScratchReg1Index)
164 .addReg(Reg1Index);
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000165
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000166 // create fstod %f21,%f2
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000167 BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD))
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000168 .addReg(ScratchReg2Index)
169 .addReg(Reg2Index);
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000170
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000171 // create fmuld %f0,%f2,%f8
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000172 BuildMI(MBB, MBBI, DL, TII.get(SP::FMULD))
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000173 .addReg(Reg3Index)
174 .addReg(ScratchReg1Index)
175 .addReg(ScratchReg2Index);
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000176
177 MI.eraseFromParent();
178 MBBI = NMBBI;
179
180 Modified = true;
181 }
182 }
183 }
184 }
185
186 return Modified;
187}
188
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000189//*****************************************************************************
190//**** ReplaceFMULS pass
191//*****************************************************************************
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000192// This pass fixes the incorrectly working FMULS instruction that exists for
193// some earlier versions of the LEON processor line.
194//
195// This pass converts the FMULS operands to double precision in scratch
196// registers, then calculates the result with the FMULD instruction.
197// The pass should replace operations of the form:
198// fmuls %f20,%f21,%f8
199// with the sequence:
200// fstod %f20,%f0
201// fstod %f21,%f2
202// fmuld %f0,%f2,%f8
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000203//
204char ReplaceFMULS::ID = 0;
205
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000206ReplaceFMULS::ReplaceFMULS(TargetMachine &tm)
207 : LEONMachineFunctionPass(tm, ID) {}
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000208
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000209bool ReplaceFMULS::runOnMachineFunction(MachineFunction &MF) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000210 Subtarget = &MF.getSubtarget<SparcSubtarget>();
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000211 const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000212 DebugLoc DL = DebugLoc();
213
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000214 bool Modified = false;
215 for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
216 MachineBasicBlock &MBB = *MFI;
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000217 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000218 MachineInstr &MI = *MBBI;
219 unsigned Opcode = MI.getOpcode();
220
221 const int UNASSIGNED_INDEX = -1;
222 int Reg1Index = UNASSIGNED_INDEX;
223 int Reg2Index = UNASSIGNED_INDEX;
224 int Reg3Index = UNASSIGNED_INDEX;
225
226 if (Opcode == SP::FMULS && MI.getNumOperands() == 3) {
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000227 // take the registers from fmuls %f20,%f21,%f8
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000228 Reg1Index = MI.getOperand(0).getReg();
229 Reg2Index = MI.getOperand(1).getReg();
230 Reg3Index = MI.getOperand(2).getReg();
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000231 }
232
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000233 if (Reg1Index != UNASSIGNED_INDEX && Reg2Index != UNASSIGNED_INDEX &&
234 Reg3Index != UNASSIGNED_INDEX) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000235 clearUsedRegisterList();
236 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000237 // Whatever Reg3Index is hasn't been used yet, so we need to reserve it.
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000238 markRegisterUsed(Reg3Index);
239 const int ScratchReg1Index = getUnusedFPRegister(MF.getRegInfo());
240 markRegisterUsed(ScratchReg1Index);
241 const int ScratchReg2Index = getUnusedFPRegister(MF.getRegInfo());
242 markRegisterUsed(ScratchReg2Index);
243
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000244 if (ScratchReg1Index == UNASSIGNED_INDEX ||
245 ScratchReg2Index == UNASSIGNED_INDEX) {
246 errs() << "Cannot allocate free scratch registers for the "
247 "ReplaceFMULS pass."
248 << "\n";
249 } else {
250 // create fstod %f20,%f0
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(ScratchReg1Index)
253 .addReg(Reg1Index);
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000254
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000255 // create fstod %f21,%f2
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000256 BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD))
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000257 .addReg(ScratchReg2Index)
258 .addReg(Reg2Index);
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000259
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000260 // create fmuld %f0,%f2,%f8
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000261 BuildMI(MBB, MBBI, DL, TII.get(SP::FMULD))
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000262 .addReg(Reg3Index)
263 .addReg(ScratchReg1Index)
264 .addReg(ScratchReg2Index);
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000265
266 MI.eraseFromParent();
267 MBBI = NMBBI;
268
269 Modified = true;
270 }
271 }
272 }
273 }
274
275 return Modified;
276}
277
Chris Dewhurst2c3cdd62016-10-19 14:01:06 +0000278
279//*****************************************************************************
280//**** DetectRoundChange pass
281//*****************************************************************************
282// To prevent any explicit change of the default rounding mode, this pass
283// detects any call of the fesetround function.
284// A warning is generated to ensure the user knows this has happened.
285//
286// Detects an erratum in UT699 LEON 3 processor
287
288char DetectRoundChange::ID = 0;
289
290DetectRoundChange::DetectRoundChange(TargetMachine &tm)
291 : LEONMachineFunctionPass(tm, ID) {}
292
293bool DetectRoundChange::runOnMachineFunction(MachineFunction &MF) {
294 Subtarget = &MF.getSubtarget<SparcSubtarget>();
295
296 bool Modified = false;
297 for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
298 MachineBasicBlock &MBB = *MFI;
299 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
300 MachineInstr &MI = *MBBI;
301 unsigned Opcode = MI.getOpcode();
302 if (Opcode == SP::CALL && MI.getNumOperands() > 0) {
303 MachineOperand &MO = MI.getOperand(0);
304
305 if (MO.isGlobal()) {
306 StringRef FuncName = MO.getGlobal()->getName();
307 if (FuncName.compare_lower("fesetround") == 0) {
308 errs() << "Error: You are using the detectroundchange "
309 "option to detect rounding changes that will "
310 "cause LEON errata. The only way to fix this "
311 "is to remove the call to fesetround from "
312 "the source code.\n";
313 }
314 }
315 }
316 }
317 }
318
319 return Modified;
320}
321
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000322//*****************************************************************************
323//**** FixAllFDIVSQRT pass
324//*****************************************************************************
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000325// This pass fixes the incorrectly working FDIVx and FSQRTx instructions that
326// exist for some earlier versions of the LEON processor line. Five NOP
327// instructions need to be inserted after these instructions to ensure the
328// correct result is placed in the destination registers before they are used.
329//
330// This pass implements two fixes:
331// 1) fixing the FSQRTS and FSQRTD instructions.
332// 2) fixing the FDIVS and FDIVD instructions.
333//
334// FSQRTS and FDIVS are converted to FDIVD and FSQRTD respectively earlier in
335// the pipeline when this option is enabled, so this pass needs only to deal
336// with the changes that still need implementing for the "double" versions
337// of these instructions.
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000338//
339char FixAllFDIVSQRT::ID = 0;
340
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000341FixAllFDIVSQRT::FixAllFDIVSQRT(TargetMachine &tm)
342 : LEONMachineFunctionPass(tm, ID) {}
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000343
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000344bool FixAllFDIVSQRT::runOnMachineFunction(MachineFunction &MF) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000345 Subtarget = &MF.getSubtarget<SparcSubtarget>();
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000346 const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000347 DebugLoc DL = DebugLoc();
348
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000349 bool Modified = false;
350 for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
351 MachineBasicBlock &MBB = *MFI;
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000352 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000353 MachineInstr &MI = *MBBI;
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000354 unsigned Opcode = MI.getOpcode();
355
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000356 // Note: FDIVS and FSQRTS cannot be generated when this erratum fix is
357 // switched on so we don't need to check for them here. They will
358 // already have been converted to FSQRTD or FDIVD earlier in the
359 // pipeline.
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000360 if (Opcode == SP::FSQRTD || Opcode == SP::FDIVD) {
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000361 for (int InsertedCount = 0; InsertedCount < 5; InsertedCount++)
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000362 BuildMI(MBB, MBBI, DL, TII.get(SP::NOP));
363
364 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000365 for (int InsertedCount = 0; InsertedCount < 28; InsertedCount++)
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000366 BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP));
367
368 Modified = true;
369 }
370 }
371 }
372
373 return Modified;
374}