1 //===------ LeonPasses.cpp - Define passes specific to LEON ---------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 //===----------------------------------------------------------------------===//
13 #include "LeonPasses.h"
14 #include "llvm/CodeGen/ISDOpcodes.h"
15 #include "llvm/CodeGen/MachineFunction.h"
16 #include "llvm/CodeGen/MachineInstr.h"
17 #include "llvm/CodeGen/MachineInstrBuilder.h"
18 #include "llvm/CodeGen/MachineRegisterInfo.h"
19 #include "llvm/IR/DiagnosticInfo.h"
20 #include "llvm/IR/LLVMContext.h"
21 #include "llvm/Support/raw_ostream.h"
24 LEONMachineFunctionPass::LEONMachineFunctionPass(char &ID)
25 : MachineFunctionPass(ID) {}
27 int LEONMachineFunctionPass::GetRegIndexForOperand(MachineInstr &MI,
29 if (MI.getNumOperands() > 0) {
30 if (OperandIndex == LAST_OPERAND) {
31 OperandIndex = MI.getNumOperands() - 1;
34 if (MI.getNumOperands() > (unsigned)OperandIndex &&
35 MI.getOperand(OperandIndex).isReg()) {
36 return (int)MI.getOperand(OperandIndex).getReg();
40 static int NotFoundIndex = -10;
41 // Return a different number each time to avoid any comparisons between the
47 // finds a new free FP register
48 // checks also the AllocatedRegisters vector
49 int LEONMachineFunctionPass::getUnusedFPRegister(MachineRegisterInfo &MRI) {
50 for (int RegisterIndex = SP::F0; RegisterIndex <= SP::F31; ++RegisterIndex) {
51 if (!MRI.isPhysRegUsed(RegisterIndex) &&
52 !is_contained(UsedRegisters, RegisterIndex)) {
60 //*****************************************************************************
61 //**** InsertNOPLoad pass
62 //*****************************************************************************
63 // 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.
68 // This pass inserts a NOP after any LD or LDF instruction.
70 char InsertNOPLoad::ID = 0;
72 InsertNOPLoad::InsertNOPLoad() : LEONMachineFunctionPass(ID) {}
74 bool InsertNOPLoad::runOnMachineFunction(MachineFunction &MF) {
75 Subtarget = &MF.getSubtarget<SparcSubtarget>();
76 const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
77 DebugLoc DL = DebugLoc();
79 bool Modified = false;
80 for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
81 MachineBasicBlock &MBB = *MFI;
82 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
83 MachineInstr &MI = *MBBI;
84 unsigned Opcode = MI.getOpcode();
85 if (Opcode >= SP::LDDArr && Opcode <= SP::LDrr) {
86 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
87 BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP));
96 //*****************************************************************************
98 //*****************************************************************************
99 // This pass fixes the incorrectly working FSMULD instruction that exists for
100 // some earlier versions of the LEON processor line.
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:
111 char FixFSMULD::ID = 0;
113 FixFSMULD::FixFSMULD() : LEONMachineFunctionPass(ID) {}
115 bool FixFSMULD::runOnMachineFunction(MachineFunction &MF) {
116 Subtarget = &MF.getSubtarget<SparcSubtarget>();
117 const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
118 DebugLoc DL = DebugLoc();
120 bool Modified = false;
121 for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
122 MachineBasicBlock &MBB = *MFI;
123 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
125 MachineInstr &MI = *MBBI;
126 unsigned Opcode = MI.getOpcode();
128 const int UNASSIGNED_INDEX = -1;
129 int Reg1Index = UNASSIGNED_INDEX;
130 int Reg2Index = UNASSIGNED_INDEX;
131 int Reg3Index = UNASSIGNED_INDEX;
133 if (Opcode == SP::FSMULD && MI.getNumOperands() == 3) {
134 // take the registers from fsmuld %f20,%f21,%f8
135 Reg1Index = MI.getOperand(0).getReg();
136 Reg2Index = MI.getOperand(1).getReg();
137 Reg3Index = MI.getOperand(2).getReg();
140 if (Reg1Index != UNASSIGNED_INDEX && Reg2Index != UNASSIGNED_INDEX &&
141 Reg3Index != UNASSIGNED_INDEX) {
142 clearUsedRegisterList();
143 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
144 // Whatever Reg3Index is hasn't been used yet, so we need to reserve it.
145 markRegisterUsed(Reg3Index);
146 const int ScratchReg1Index = getUnusedFPRegister(MF.getRegInfo());
147 markRegisterUsed(ScratchReg1Index);
148 const int ScratchReg2Index = getUnusedFPRegister(MF.getRegInfo());
149 markRegisterUsed(ScratchReg2Index);
151 if (ScratchReg1Index == UNASSIGNED_INDEX ||
152 ScratchReg2Index == UNASSIGNED_INDEX) {
153 errs() << "Cannot allocate free scratch registers for the FixFSMULD "
157 // create fstod %f20,%f0
158 BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD))
159 .addReg(ScratchReg1Index)
162 // create fstod %f21,%f2
163 BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD))
164 .addReg(ScratchReg2Index)
167 // create fmuld %f0,%f2,%f8
168 BuildMI(MBB, MBBI, DL, TII.get(SP::FMULD))
170 .addReg(ScratchReg1Index)
171 .addReg(ScratchReg2Index);
173 MI.eraseFromParent();
185 //*****************************************************************************
186 //**** ReplaceFMULS pass
187 //*****************************************************************************
188 // This pass fixes the incorrectly working FMULS instruction that exists for
189 // some earlier versions of the LEON processor line.
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:
200 char ReplaceFMULS::ID = 0;
202 ReplaceFMULS::ReplaceFMULS() : LEONMachineFunctionPass(ID) {}
204 bool ReplaceFMULS::runOnMachineFunction(MachineFunction &MF) {
205 Subtarget = &MF.getSubtarget<SparcSubtarget>();
206 const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
207 DebugLoc DL = DebugLoc();
209 bool Modified = false;
210 for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
211 MachineBasicBlock &MBB = *MFI;
212 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
213 MachineInstr &MI = *MBBI;
214 unsigned Opcode = MI.getOpcode();
216 const int UNASSIGNED_INDEX = -1;
217 int Reg1Index = UNASSIGNED_INDEX;
218 int Reg2Index = UNASSIGNED_INDEX;
219 int Reg3Index = UNASSIGNED_INDEX;
221 if (Opcode == SP::FMULS && MI.getNumOperands() == 3) {
222 // take the registers from fmuls %f20,%f21,%f8
223 Reg1Index = MI.getOperand(0).getReg();
224 Reg2Index = MI.getOperand(1).getReg();
225 Reg3Index = MI.getOperand(2).getReg();
228 if (Reg1Index != UNASSIGNED_INDEX && Reg2Index != UNASSIGNED_INDEX &&
229 Reg3Index != UNASSIGNED_INDEX) {
230 clearUsedRegisterList();
231 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
232 // Whatever Reg3Index is hasn't been used yet, so we need to reserve it.
233 markRegisterUsed(Reg3Index);
234 const int ScratchReg1Index = getUnusedFPRegister(MF.getRegInfo());
235 markRegisterUsed(ScratchReg1Index);
236 const int ScratchReg2Index = getUnusedFPRegister(MF.getRegInfo());
237 markRegisterUsed(ScratchReg2Index);
239 if (ScratchReg1Index == UNASSIGNED_INDEX ||
240 ScratchReg2Index == UNASSIGNED_INDEX) {
241 errs() << "Cannot allocate free scratch registers for the "
245 // create fstod %f20,%f0
246 BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD))
247 .addReg(ScratchReg1Index)
250 // create fstod %f21,%f2
251 BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD))
252 .addReg(ScratchReg2Index)
255 // create fmuld %f0,%f2,%f8
256 BuildMI(MBB, MBBI, DL, TII.get(SP::FMULD))
258 .addReg(ScratchReg1Index)
259 .addReg(ScratchReg2Index);
261 MI.eraseFromParent();
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.
281 // Detects an erratum in UT699 LEON 3 processor
283 char DetectRoundChange::ID = 0;
285 DetectRoundChange::DetectRoundChange() : LEONMachineFunctionPass(ID) {}
287 bool DetectRoundChange::runOnMachineFunction(MachineFunction &MF) {
288 Subtarget = &MF.getSubtarget<SparcSubtarget>();
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);
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";
316 //*****************************************************************************
317 //**** FixAllFDIVSQRT pass
318 //*****************************************************************************
319 // 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.
324 // This pass implements two fixes:
325 // 1) fixing the FSQRTS and FSQRTD instructions.
326 // 2) fixing the FDIVS and FDIVD instructions.
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.
333 char FixAllFDIVSQRT::ID = 0;
335 FixAllFDIVSQRT::FixAllFDIVSQRT() : LEONMachineFunctionPass(ID) {}
337 bool FixAllFDIVSQRT::runOnMachineFunction(MachineFunction &MF) {
338 Subtarget = &MF.getSubtarget<SparcSubtarget>();
339 const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
340 DebugLoc DL = DebugLoc();
342 bool Modified = false;
343 for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
344 MachineBasicBlock &MBB = *MFI;
345 for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
346 MachineInstr &MI = *MBBI;
347 unsigned Opcode = MI.getOpcode();
349 // 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
353 if (Opcode == SP::FSQRTD || Opcode == SP::FDIVD) {
354 for (int InsertedCount = 0; InsertedCount < 5; InsertedCount++)
355 BuildMI(MBB, MBBI, DL, TII.get(SP::NOP));
357 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
358 for (int InsertedCount = 0; InsertedCount < 28; InsertedCount++)
359 BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP));