blob: 46ae9ccc783f5ea873bb19218d779929e331a112 [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) &&
David Majnemer0d955d02016-08-11 22:21:41 +000054 !is_contained(UsedRegisters, RegisterIndex)) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +000055 return RegisterIndex;
56 }
57 }
58
59 return -1;
60}
61
Chris Dewhurst4f7cac32016-05-23 10:56:36 +000062//*****************************************************************************
63//**** InsertNOPLoad pass
64//*****************************************************************************
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000065// This pass fixes the incorrectly working Load instructions that exists for
66// some earlier versions of the LEON processor line. NOP instructions must
67// be inserted after the load instruction to ensure that the Load instruction
68// behaves as expected for these processors.
69//
70// This pass inserts a NOP after any LD or LDF instruction.
Chris Dewhurst4f7cac32016-05-23 10:56:36 +000071//
72char InsertNOPLoad::ID = 0;
73
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000074InsertNOPLoad::InsertNOPLoad(TargetMachine &tm)
75 : LEONMachineFunctionPass(tm, ID) {}
Chris Dewhurst4f7cac32016-05-23 10:56:36 +000076
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000077bool InsertNOPLoad::runOnMachineFunction(MachineFunction &MF) {
Chris Dewhurst4f7cac32016-05-23 10:56:36 +000078 Subtarget = &MF.getSubtarget<SparcSubtarget>();
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000079 const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
Chris Dewhurst4f7cac32016-05-23 10:56:36 +000080 DebugLoc DL = DebugLoc();
81
82 bool Modified = false;
83 for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
84 MachineBasicBlock &MBB = *MFI;
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000085 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
Chris Dewhurst4f7cac32016-05-23 10:56:36 +000086 MachineInstr &MI = *MBBI;
87 unsigned Opcode = MI.getOpcode();
Chris Dewhurst2bad85c2016-06-27 14:19:19 +000088 if (Opcode >= SP::LDDArr && Opcode <= SP::LDrr) {
Chris Dewhurst4f7cac32016-05-23 10:56:36 +000089 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
90 BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP));
91 Modified = true;
Chris Dewhurst4f7cac32016-05-23 10:56:36 +000092 }
93 }
94 }
95
96 return Modified;
97}
Chris Dewhurst0c1e0022016-06-19 11:03:28 +000098
99//*****************************************************************************
100//**** FixFSMULD pass
101//*****************************************************************************
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000102// This pass fixes the incorrectly working FSMULD instruction that exists for
103// some earlier versions of the LEON processor line.
104//
105// The pass should convert the FSMULD operands to double precision in scratch
106// registers, then calculate the result with the FMULD instruction. Therefore,
107// the pass should replace operations of the form:
108// fsmuld %f20,%f21,%f8
109// with the sequence:
110// fstod %f20,%f0
111// fstod %f21,%f2
112// fmuld %f0,%f2,%f8
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000113//
114char FixFSMULD::ID = 0;
115
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000116FixFSMULD::FixFSMULD(TargetMachine &tm) : LEONMachineFunctionPass(tm, ID) {}
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000117
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000118bool FixFSMULD::runOnMachineFunction(MachineFunction &MF) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000119 Subtarget = &MF.getSubtarget<SparcSubtarget>();
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000120 const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000121 DebugLoc DL = DebugLoc();
122
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000123 bool Modified = false;
124 for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
125 MachineBasicBlock &MBB = *MFI;
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000126 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000127
128 MachineInstr &MI = *MBBI;
129 unsigned Opcode = MI.getOpcode();
130
131 const int UNASSIGNED_INDEX = -1;
132 int Reg1Index = UNASSIGNED_INDEX;
133 int Reg2Index = UNASSIGNED_INDEX;
134 int Reg3Index = UNASSIGNED_INDEX;
135
136 if (Opcode == SP::FSMULD && MI.getNumOperands() == 3) {
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000137 // take the registers from fsmuld %f20,%f21,%f8
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000138 Reg1Index = MI.getOperand(0).getReg();
139 Reg2Index = MI.getOperand(1).getReg();
140 Reg3Index = MI.getOperand(2).getReg();
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000141 }
142
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000143 if (Reg1Index != UNASSIGNED_INDEX && Reg2Index != UNASSIGNED_INDEX &&
144 Reg3Index != UNASSIGNED_INDEX) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000145 clearUsedRegisterList();
146 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000147 // Whatever Reg3Index is hasn't been used yet, so we need to reserve it.
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000148 markRegisterUsed(Reg3Index);
149 const int ScratchReg1Index = getUnusedFPRegister(MF.getRegInfo());
150 markRegisterUsed(ScratchReg1Index);
151 const int ScratchReg2Index = getUnusedFPRegister(MF.getRegInfo());
152 markRegisterUsed(ScratchReg2Index);
153
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000154 if (ScratchReg1Index == UNASSIGNED_INDEX ||
155 ScratchReg2Index == UNASSIGNED_INDEX) {
156 errs() << "Cannot allocate free scratch registers for the FixFSMULD "
157 "pass."
158 << "\n";
159 } else {
160 // create fstod %f20,%f0
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000161 BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD))
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000162 .addReg(ScratchReg1Index)
163 .addReg(Reg1Index);
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000164
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000165 // create fstod %f21,%f2
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000166 BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD))
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000167 .addReg(ScratchReg2Index)
168 .addReg(Reg2Index);
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000169
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000170 // create fmuld %f0,%f2,%f8
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000171 BuildMI(MBB, MBBI, DL, TII.get(SP::FMULD))
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000172 .addReg(Reg3Index)
173 .addReg(ScratchReg1Index)
174 .addReg(ScratchReg2Index);
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000175
176 MI.eraseFromParent();
177 MBBI = NMBBI;
178
179 Modified = true;
180 }
181 }
182 }
183 }
184
185 return Modified;
186}
187
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000188//*****************************************************************************
189//**** ReplaceFMULS pass
190//*****************************************************************************
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000191// This pass fixes the incorrectly working FMULS instruction that exists for
192// some earlier versions of the LEON processor line.
193//
194// This pass converts the FMULS operands to double precision in scratch
195// registers, then calculates the result with the FMULD instruction.
196// The pass should replace operations of the form:
197// fmuls %f20,%f21,%f8
198// with the sequence:
199// fstod %f20,%f0
200// fstod %f21,%f2
201// fmuld %f0,%f2,%f8
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000202//
203char ReplaceFMULS::ID = 0;
204
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000205ReplaceFMULS::ReplaceFMULS(TargetMachine &tm)
206 : LEONMachineFunctionPass(tm, ID) {}
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000207
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000208bool ReplaceFMULS::runOnMachineFunction(MachineFunction &MF) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000209 Subtarget = &MF.getSubtarget<SparcSubtarget>();
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000210 const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000211 DebugLoc DL = DebugLoc();
212
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000213 bool Modified = false;
214 for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
215 MachineBasicBlock &MBB = *MFI;
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000216 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000217 MachineInstr &MI = *MBBI;
218 unsigned Opcode = MI.getOpcode();
219
220 const int UNASSIGNED_INDEX = -1;
221 int Reg1Index = UNASSIGNED_INDEX;
222 int Reg2Index = UNASSIGNED_INDEX;
223 int Reg3Index = UNASSIGNED_INDEX;
224
225 if (Opcode == SP::FMULS && MI.getNumOperands() == 3) {
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000226 // take the registers from fmuls %f20,%f21,%f8
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000227 Reg1Index = MI.getOperand(0).getReg();
228 Reg2Index = MI.getOperand(1).getReg();
229 Reg3Index = MI.getOperand(2).getReg();
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000230 }
231
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000232 if (Reg1Index != UNASSIGNED_INDEX && Reg2Index != UNASSIGNED_INDEX &&
233 Reg3Index != UNASSIGNED_INDEX) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000234 clearUsedRegisterList();
235 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000236 // Whatever Reg3Index is hasn't been used yet, so we need to reserve it.
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000237 markRegisterUsed(Reg3Index);
238 const int ScratchReg1Index = getUnusedFPRegister(MF.getRegInfo());
239 markRegisterUsed(ScratchReg1Index);
240 const int ScratchReg2Index = getUnusedFPRegister(MF.getRegInfo());
241 markRegisterUsed(ScratchReg2Index);
242
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000243 if (ScratchReg1Index == UNASSIGNED_INDEX ||
244 ScratchReg2Index == UNASSIGNED_INDEX) {
245 errs() << "Cannot allocate free scratch registers for the "
246 "ReplaceFMULS pass."
247 << "\n";
248 } else {
249 // create fstod %f20,%f0
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000250 BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD))
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000251 .addReg(ScratchReg1Index)
252 .addReg(Reg1Index);
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000253
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000254 // create fstod %f21,%f2
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000255 BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD))
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000256 .addReg(ScratchReg2Index)
257 .addReg(Reg2Index);
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000258
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000259 // create fmuld %f0,%f2,%f8
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000260 BuildMI(MBB, MBBI, DL, TII.get(SP::FMULD))
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000261 .addReg(Reg3Index)
262 .addReg(ScratchReg1Index)
263 .addReg(ScratchReg2Index);
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000264
265 MI.eraseFromParent();
266 MBBI = NMBBI;
267
268 Modified = true;
269 }
270 }
271 }
272 }
273
274 return Modified;
275}
276
277//*****************************************************************************
278//**** FixAllFDIVSQRT pass
279//*****************************************************************************
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000280// This pass fixes the incorrectly working FDIVx and FSQRTx instructions that
281// exist for some earlier versions of the LEON processor line. Five NOP
282// instructions need to be inserted after these instructions to ensure the
283// correct result is placed in the destination registers before they are used.
284//
285// This pass implements two fixes:
286// 1) fixing the FSQRTS and FSQRTD instructions.
287// 2) fixing the FDIVS and FDIVD instructions.
288//
289// FSQRTS and FDIVS are converted to FDIVD and FSQRTD respectively earlier in
290// the pipeline when this option is enabled, so this pass needs only to deal
291// with the changes that still need implementing for the "double" versions
292// of these instructions.
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000293//
294char FixAllFDIVSQRT::ID = 0;
295
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000296FixAllFDIVSQRT::FixAllFDIVSQRT(TargetMachine &tm)
297 : LEONMachineFunctionPass(tm, ID) {}
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000298
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000299bool FixAllFDIVSQRT::runOnMachineFunction(MachineFunction &MF) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000300 Subtarget = &MF.getSubtarget<SparcSubtarget>();
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000301 const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000302 DebugLoc DL = DebugLoc();
303
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000304 bool Modified = false;
305 for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
306 MachineBasicBlock &MBB = *MFI;
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000307 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000308 MachineInstr &MI = *MBBI;
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000309 unsigned Opcode = MI.getOpcode();
310
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000311 // Note: FDIVS and FSQRTS cannot be generated when this erratum fix is
312 // switched on so we don't need to check for them here. They will
313 // already have been converted to FSQRTD or FDIVD earlier in the
314 // pipeline.
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000315 if (Opcode == SP::FSQRTD || Opcode == SP::FDIVD) {
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000316 for (int InsertedCount = 0; InsertedCount < 5; InsertedCount++)
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000317 BuildMI(MBB, MBBI, DL, TII.get(SP::NOP));
318
319 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
Chris Dewhurst2bad85c2016-06-27 14:19:19 +0000320 for (int InsertedCount = 0; InsertedCount < 28; InsertedCount++)
Chris Dewhurst0c1e0022016-06-19 11:03:28 +0000321 BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP));
322
323 Modified = true;
324 }
325 }
326 }
327
328 return Modified;
329}