1*9880d681SAndroid Build Coastguard Worker //===------ LeonPasses.cpp - Define passes specific to LEON ---------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker //
11*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
12*9880d681SAndroid Build Coastguard Worker
13*9880d681SAndroid Build Coastguard Worker #include "LeonPasses.h"
14*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/ISDOpcodes.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunction.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstr.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstrBuilder.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineRegisterInfo.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/LLVMContext.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
21*9880d681SAndroid Build Coastguard Worker using namespace llvm;
22*9880d681SAndroid Build Coastguard Worker
LEONMachineFunctionPass(TargetMachine & tm,char & ID)23*9880d681SAndroid Build Coastguard Worker LEONMachineFunctionPass::LEONMachineFunctionPass(TargetMachine &tm, char &ID)
24*9880d681SAndroid Build Coastguard Worker : MachineFunctionPass(ID) {}
25*9880d681SAndroid Build Coastguard Worker
LEONMachineFunctionPass(char & ID)26*9880d681SAndroid Build Coastguard Worker LEONMachineFunctionPass::LEONMachineFunctionPass(char &ID)
27*9880d681SAndroid Build Coastguard Worker : MachineFunctionPass(ID) {}
28*9880d681SAndroid Build Coastguard Worker
GetRegIndexForOperand(MachineInstr & MI,int OperandIndex)29*9880d681SAndroid Build Coastguard Worker int LEONMachineFunctionPass::GetRegIndexForOperand(MachineInstr &MI,
30*9880d681SAndroid Build Coastguard Worker int OperandIndex) {
31*9880d681SAndroid Build Coastguard Worker if (MI.getNumOperands() > 0) {
32*9880d681SAndroid Build Coastguard Worker if (OperandIndex == LAST_OPERAND) {
33*9880d681SAndroid Build Coastguard Worker OperandIndex = MI.getNumOperands() - 1;
34*9880d681SAndroid Build Coastguard Worker }
35*9880d681SAndroid Build Coastguard Worker
36*9880d681SAndroid Build Coastguard Worker if (MI.getNumOperands() > (unsigned)OperandIndex &&
37*9880d681SAndroid Build Coastguard Worker MI.getOperand(OperandIndex).isReg()) {
38*9880d681SAndroid Build Coastguard Worker return (int)MI.getOperand(OperandIndex).getReg();
39*9880d681SAndroid Build Coastguard Worker }
40*9880d681SAndroid Build Coastguard Worker }
41*9880d681SAndroid Build Coastguard Worker
42*9880d681SAndroid Build Coastguard Worker static int NotFoundIndex = -10;
43*9880d681SAndroid Build Coastguard Worker // Return a different number each time to avoid any comparisons between the
44*9880d681SAndroid Build Coastguard Worker // values returned.
45*9880d681SAndroid Build Coastguard Worker NotFoundIndex -= 10;
46*9880d681SAndroid Build Coastguard Worker return NotFoundIndex;
47*9880d681SAndroid Build Coastguard Worker }
48*9880d681SAndroid Build Coastguard Worker
49*9880d681SAndroid Build Coastguard Worker // finds a new free FP register
50*9880d681SAndroid Build Coastguard Worker // checks also the AllocatedRegisters vector
getUnusedFPRegister(MachineRegisterInfo & MRI)51*9880d681SAndroid Build Coastguard Worker int LEONMachineFunctionPass::getUnusedFPRegister(MachineRegisterInfo &MRI) {
52*9880d681SAndroid Build Coastguard Worker for (int RegisterIndex = SP::F0; RegisterIndex <= SP::F31; ++RegisterIndex) {
53*9880d681SAndroid Build Coastguard Worker if (!MRI.isPhysRegUsed(RegisterIndex) &&
54*9880d681SAndroid Build Coastguard Worker !(std::find(UsedRegisters.begin(), UsedRegisters.end(),
55*9880d681SAndroid Build Coastguard Worker RegisterIndex) != UsedRegisters.end())) {
56*9880d681SAndroid Build Coastguard Worker return RegisterIndex;
57*9880d681SAndroid Build Coastguard Worker }
58*9880d681SAndroid Build Coastguard Worker }
59*9880d681SAndroid Build Coastguard Worker
60*9880d681SAndroid Build Coastguard Worker return -1;
61*9880d681SAndroid Build Coastguard Worker }
62*9880d681SAndroid Build Coastguard Worker
63*9880d681SAndroid Build Coastguard Worker //*****************************************************************************
64*9880d681SAndroid Build Coastguard Worker //**** InsertNOPLoad pass
65*9880d681SAndroid Build Coastguard Worker //*****************************************************************************
66*9880d681SAndroid Build Coastguard Worker // This pass fixes the incorrectly working Load instructions that exists for
67*9880d681SAndroid Build Coastguard Worker // some earlier versions of the LEON processor line. NOP instructions must
68*9880d681SAndroid Build Coastguard Worker // be inserted after the load instruction to ensure that the Load instruction
69*9880d681SAndroid Build Coastguard Worker // behaves as expected for these processors.
70*9880d681SAndroid Build Coastguard Worker //
71*9880d681SAndroid Build Coastguard Worker // This pass inserts a NOP after any LD or LDF instruction.
72*9880d681SAndroid Build Coastguard Worker //
73*9880d681SAndroid Build Coastguard Worker char InsertNOPLoad::ID = 0;
74*9880d681SAndroid Build Coastguard Worker
InsertNOPLoad(TargetMachine & tm)75*9880d681SAndroid Build Coastguard Worker InsertNOPLoad::InsertNOPLoad(TargetMachine &tm)
76*9880d681SAndroid Build Coastguard Worker : LEONMachineFunctionPass(tm, ID) {}
77*9880d681SAndroid Build Coastguard Worker
runOnMachineFunction(MachineFunction & MF)78*9880d681SAndroid Build Coastguard Worker bool InsertNOPLoad::runOnMachineFunction(MachineFunction &MF) {
79*9880d681SAndroid Build Coastguard Worker Subtarget = &MF.getSubtarget<SparcSubtarget>();
80*9880d681SAndroid Build Coastguard Worker const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
81*9880d681SAndroid Build Coastguard Worker DebugLoc DL = DebugLoc();
82*9880d681SAndroid Build Coastguard Worker
83*9880d681SAndroid Build Coastguard Worker bool Modified = false;
84*9880d681SAndroid Build Coastguard Worker for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
85*9880d681SAndroid Build Coastguard Worker MachineBasicBlock &MBB = *MFI;
86*9880d681SAndroid Build Coastguard Worker for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
87*9880d681SAndroid Build Coastguard Worker MachineInstr &MI = *MBBI;
88*9880d681SAndroid Build Coastguard Worker unsigned Opcode = MI.getOpcode();
89*9880d681SAndroid Build Coastguard Worker if (Opcode >= SP::LDDArr && Opcode <= SP::LDrr) {
90*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator NMBBI = std::next(MBBI);
91*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP));
92*9880d681SAndroid Build Coastguard Worker Modified = true;
93*9880d681SAndroid Build Coastguard Worker } else if (MI.isInlineAsm()) {
94*9880d681SAndroid Build Coastguard Worker // Look for an inline ld or ldf instruction.
95*9880d681SAndroid Build Coastguard Worker StringRef AsmString =
96*9880d681SAndroid Build Coastguard Worker MI.getOperand(InlineAsm::MIOp_AsmString).getSymbolName();
97*9880d681SAndroid Build Coastguard Worker if (AsmString.startswith_lower("ld")) {
98*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator NMBBI = std::next(MBBI);
99*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP));
100*9880d681SAndroid Build Coastguard Worker Modified = true;
101*9880d681SAndroid Build Coastguard Worker }
102*9880d681SAndroid Build Coastguard Worker }
103*9880d681SAndroid Build Coastguard Worker }
104*9880d681SAndroid Build Coastguard Worker }
105*9880d681SAndroid Build Coastguard Worker
106*9880d681SAndroid Build Coastguard Worker return Modified;
107*9880d681SAndroid Build Coastguard Worker }
108*9880d681SAndroid Build Coastguard Worker
109*9880d681SAndroid Build Coastguard Worker //*****************************************************************************
110*9880d681SAndroid Build Coastguard Worker //**** FixFSMULD pass
111*9880d681SAndroid Build Coastguard Worker //*****************************************************************************
112*9880d681SAndroid Build Coastguard Worker // This pass fixes the incorrectly working FSMULD instruction that exists for
113*9880d681SAndroid Build Coastguard Worker // some earlier versions of the LEON processor line.
114*9880d681SAndroid Build Coastguard Worker //
115*9880d681SAndroid Build Coastguard Worker // The pass should convert the FSMULD operands to double precision in scratch
116*9880d681SAndroid Build Coastguard Worker // registers, then calculate the result with the FMULD instruction. Therefore,
117*9880d681SAndroid Build Coastguard Worker // the pass should replace operations of the form:
118*9880d681SAndroid Build Coastguard Worker // fsmuld %f20,%f21,%f8
119*9880d681SAndroid Build Coastguard Worker // with the sequence:
120*9880d681SAndroid Build Coastguard Worker // fstod %f20,%f0
121*9880d681SAndroid Build Coastguard Worker // fstod %f21,%f2
122*9880d681SAndroid Build Coastguard Worker // fmuld %f0,%f2,%f8
123*9880d681SAndroid Build Coastguard Worker //
124*9880d681SAndroid Build Coastguard Worker char FixFSMULD::ID = 0;
125*9880d681SAndroid Build Coastguard Worker
FixFSMULD(TargetMachine & tm)126*9880d681SAndroid Build Coastguard Worker FixFSMULD::FixFSMULD(TargetMachine &tm) : LEONMachineFunctionPass(tm, ID) {}
127*9880d681SAndroid Build Coastguard Worker
runOnMachineFunction(MachineFunction & MF)128*9880d681SAndroid Build Coastguard Worker bool FixFSMULD::runOnMachineFunction(MachineFunction &MF) {
129*9880d681SAndroid Build Coastguard Worker Subtarget = &MF.getSubtarget<SparcSubtarget>();
130*9880d681SAndroid Build Coastguard Worker const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
131*9880d681SAndroid Build Coastguard Worker DebugLoc DL = DebugLoc();
132*9880d681SAndroid Build Coastguard Worker
133*9880d681SAndroid Build Coastguard Worker bool Modified = false;
134*9880d681SAndroid Build Coastguard Worker for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
135*9880d681SAndroid Build Coastguard Worker MachineBasicBlock &MBB = *MFI;
136*9880d681SAndroid Build Coastguard Worker for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
137*9880d681SAndroid Build Coastguard Worker
138*9880d681SAndroid Build Coastguard Worker MachineInstr &MI = *MBBI;
139*9880d681SAndroid Build Coastguard Worker unsigned Opcode = MI.getOpcode();
140*9880d681SAndroid Build Coastguard Worker
141*9880d681SAndroid Build Coastguard Worker const int UNASSIGNED_INDEX = -1;
142*9880d681SAndroid Build Coastguard Worker int Reg1Index = UNASSIGNED_INDEX;
143*9880d681SAndroid Build Coastguard Worker int Reg2Index = UNASSIGNED_INDEX;
144*9880d681SAndroid Build Coastguard Worker int Reg3Index = UNASSIGNED_INDEX;
145*9880d681SAndroid Build Coastguard Worker
146*9880d681SAndroid Build Coastguard Worker if (Opcode == SP::FSMULD && MI.getNumOperands() == 3) {
147*9880d681SAndroid Build Coastguard Worker // take the registers from fsmuld %f20,%f21,%f8
148*9880d681SAndroid Build Coastguard Worker Reg1Index = MI.getOperand(0).getReg();
149*9880d681SAndroid Build Coastguard Worker Reg2Index = MI.getOperand(1).getReg();
150*9880d681SAndroid Build Coastguard Worker Reg3Index = MI.getOperand(2).getReg();
151*9880d681SAndroid Build Coastguard Worker } else if (MI.isInlineAsm()) {
152*9880d681SAndroid Build Coastguard Worker StringRef AsmString =
153*9880d681SAndroid Build Coastguard Worker MI.getOperand(InlineAsm::MIOp_AsmString).getSymbolName();
154*9880d681SAndroid Build Coastguard Worker if (AsmString.startswith_lower("fsmuld")) {
155*9880d681SAndroid Build Coastguard Worker // this is an inline FSMULD instruction
156*9880d681SAndroid Build Coastguard Worker
157*9880d681SAndroid Build Coastguard Worker unsigned StartOp = InlineAsm::MIOp_FirstOperand;
158*9880d681SAndroid Build Coastguard Worker
159*9880d681SAndroid Build Coastguard Worker // extracts the registers from the inline assembly instruction
160*9880d681SAndroid Build Coastguard Worker for (unsigned i = StartOp, e = MI.getNumOperands(); i != e; ++i) {
161*9880d681SAndroid Build Coastguard Worker const MachineOperand &MO = MI.getOperand(i);
162*9880d681SAndroid Build Coastguard Worker if (MO.isReg()) {
163*9880d681SAndroid Build Coastguard Worker if (Reg1Index == UNASSIGNED_INDEX)
164*9880d681SAndroid Build Coastguard Worker Reg1Index = MO.getReg();
165*9880d681SAndroid Build Coastguard Worker else if (Reg2Index == UNASSIGNED_INDEX)
166*9880d681SAndroid Build Coastguard Worker Reg2Index = MO.getReg();
167*9880d681SAndroid Build Coastguard Worker else if (Reg3Index == UNASSIGNED_INDEX)
168*9880d681SAndroid Build Coastguard Worker Reg3Index = MO.getReg();
169*9880d681SAndroid Build Coastguard Worker }
170*9880d681SAndroid Build Coastguard Worker if (Reg3Index != UNASSIGNED_INDEX)
171*9880d681SAndroid Build Coastguard Worker break;
172*9880d681SAndroid Build Coastguard Worker }
173*9880d681SAndroid Build Coastguard Worker }
174*9880d681SAndroid Build Coastguard Worker }
175*9880d681SAndroid Build Coastguard Worker
176*9880d681SAndroid Build Coastguard Worker if (Reg1Index != UNASSIGNED_INDEX && Reg2Index != UNASSIGNED_INDEX &&
177*9880d681SAndroid Build Coastguard Worker Reg3Index != UNASSIGNED_INDEX) {
178*9880d681SAndroid Build Coastguard Worker clearUsedRegisterList();
179*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator NMBBI = std::next(MBBI);
180*9880d681SAndroid Build Coastguard Worker // Whatever Reg3Index is hasn't been used yet, so we need to reserve it.
181*9880d681SAndroid Build Coastguard Worker markRegisterUsed(Reg3Index);
182*9880d681SAndroid Build Coastguard Worker const int ScratchReg1Index = getUnusedFPRegister(MF.getRegInfo());
183*9880d681SAndroid Build Coastguard Worker markRegisterUsed(ScratchReg1Index);
184*9880d681SAndroid Build Coastguard Worker const int ScratchReg2Index = getUnusedFPRegister(MF.getRegInfo());
185*9880d681SAndroid Build Coastguard Worker markRegisterUsed(ScratchReg2Index);
186*9880d681SAndroid Build Coastguard Worker
187*9880d681SAndroid Build Coastguard Worker if (ScratchReg1Index == UNASSIGNED_INDEX ||
188*9880d681SAndroid Build Coastguard Worker ScratchReg2Index == UNASSIGNED_INDEX) {
189*9880d681SAndroid Build Coastguard Worker errs() << "Cannot allocate free scratch registers for the FixFSMULD "
190*9880d681SAndroid Build Coastguard Worker "pass."
191*9880d681SAndroid Build Coastguard Worker << "\n";
192*9880d681SAndroid Build Coastguard Worker } else {
193*9880d681SAndroid Build Coastguard Worker // create fstod %f20,%f0
194*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD))
195*9880d681SAndroid Build Coastguard Worker .addReg(ScratchReg1Index)
196*9880d681SAndroid Build Coastguard Worker .addReg(Reg1Index);
197*9880d681SAndroid Build Coastguard Worker
198*9880d681SAndroid Build Coastguard Worker // create fstod %f21,%f2
199*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD))
200*9880d681SAndroid Build Coastguard Worker .addReg(ScratchReg2Index)
201*9880d681SAndroid Build Coastguard Worker .addReg(Reg2Index);
202*9880d681SAndroid Build Coastguard Worker
203*9880d681SAndroid Build Coastguard Worker // create fmuld %f0,%f2,%f8
204*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, MBBI, DL, TII.get(SP::FMULD))
205*9880d681SAndroid Build Coastguard Worker .addReg(Reg3Index)
206*9880d681SAndroid Build Coastguard Worker .addReg(ScratchReg1Index)
207*9880d681SAndroid Build Coastguard Worker .addReg(ScratchReg2Index);
208*9880d681SAndroid Build Coastguard Worker
209*9880d681SAndroid Build Coastguard Worker MI.eraseFromParent();
210*9880d681SAndroid Build Coastguard Worker MBBI = NMBBI;
211*9880d681SAndroid Build Coastguard Worker
212*9880d681SAndroid Build Coastguard Worker Modified = true;
213*9880d681SAndroid Build Coastguard Worker }
214*9880d681SAndroid Build Coastguard Worker }
215*9880d681SAndroid Build Coastguard Worker }
216*9880d681SAndroid Build Coastguard Worker }
217*9880d681SAndroid Build Coastguard Worker
218*9880d681SAndroid Build Coastguard Worker return Modified;
219*9880d681SAndroid Build Coastguard Worker }
220*9880d681SAndroid Build Coastguard Worker
221*9880d681SAndroid Build Coastguard Worker //*****************************************************************************
222*9880d681SAndroid Build Coastguard Worker //**** ReplaceFMULS pass
223*9880d681SAndroid Build Coastguard Worker //*****************************************************************************
224*9880d681SAndroid Build Coastguard Worker // This pass fixes the incorrectly working FMULS instruction that exists for
225*9880d681SAndroid Build Coastguard Worker // some earlier versions of the LEON processor line.
226*9880d681SAndroid Build Coastguard Worker //
227*9880d681SAndroid Build Coastguard Worker // This pass converts the FMULS operands to double precision in scratch
228*9880d681SAndroid Build Coastguard Worker // registers, then calculates the result with the FMULD instruction.
229*9880d681SAndroid Build Coastguard Worker // The pass should replace operations of the form:
230*9880d681SAndroid Build Coastguard Worker // fmuls %f20,%f21,%f8
231*9880d681SAndroid Build Coastguard Worker // with the sequence:
232*9880d681SAndroid Build Coastguard Worker // fstod %f20,%f0
233*9880d681SAndroid Build Coastguard Worker // fstod %f21,%f2
234*9880d681SAndroid Build Coastguard Worker // fmuld %f0,%f2,%f8
235*9880d681SAndroid Build Coastguard Worker //
236*9880d681SAndroid Build Coastguard Worker char ReplaceFMULS::ID = 0;
237*9880d681SAndroid Build Coastguard Worker
ReplaceFMULS(TargetMachine & tm)238*9880d681SAndroid Build Coastguard Worker ReplaceFMULS::ReplaceFMULS(TargetMachine &tm)
239*9880d681SAndroid Build Coastguard Worker : LEONMachineFunctionPass(tm, ID) {}
240*9880d681SAndroid Build Coastguard Worker
runOnMachineFunction(MachineFunction & MF)241*9880d681SAndroid Build Coastguard Worker bool ReplaceFMULS::runOnMachineFunction(MachineFunction &MF) {
242*9880d681SAndroid Build Coastguard Worker Subtarget = &MF.getSubtarget<SparcSubtarget>();
243*9880d681SAndroid Build Coastguard Worker const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
244*9880d681SAndroid Build Coastguard Worker DebugLoc DL = DebugLoc();
245*9880d681SAndroid Build Coastguard Worker
246*9880d681SAndroid Build Coastguard Worker bool Modified = false;
247*9880d681SAndroid Build Coastguard Worker for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
248*9880d681SAndroid Build Coastguard Worker MachineBasicBlock &MBB = *MFI;
249*9880d681SAndroid Build Coastguard Worker for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
250*9880d681SAndroid Build Coastguard Worker MachineInstr &MI = *MBBI;
251*9880d681SAndroid Build Coastguard Worker unsigned Opcode = MI.getOpcode();
252*9880d681SAndroid Build Coastguard Worker
253*9880d681SAndroid Build Coastguard Worker const int UNASSIGNED_INDEX = -1;
254*9880d681SAndroid Build Coastguard Worker int Reg1Index = UNASSIGNED_INDEX;
255*9880d681SAndroid Build Coastguard Worker int Reg2Index = UNASSIGNED_INDEX;
256*9880d681SAndroid Build Coastguard Worker int Reg3Index = UNASSIGNED_INDEX;
257*9880d681SAndroid Build Coastguard Worker
258*9880d681SAndroid Build Coastguard Worker if (Opcode == SP::FMULS && MI.getNumOperands() == 3) {
259*9880d681SAndroid Build Coastguard Worker // take the registers from fmuls %f20,%f21,%f8
260*9880d681SAndroid Build Coastguard Worker Reg1Index = MI.getOperand(0).getReg();
261*9880d681SAndroid Build Coastguard Worker Reg2Index = MI.getOperand(1).getReg();
262*9880d681SAndroid Build Coastguard Worker Reg3Index = MI.getOperand(2).getReg();
263*9880d681SAndroid Build Coastguard Worker } else if (MI.isInlineAsm()) {
264*9880d681SAndroid Build Coastguard Worker StringRef AsmString =
265*9880d681SAndroid Build Coastguard Worker MI.getOperand(InlineAsm::MIOp_AsmString).getSymbolName();
266*9880d681SAndroid Build Coastguard Worker if (AsmString.startswith_lower("fmuls")) {
267*9880d681SAndroid Build Coastguard Worker // this is an inline FMULS instruction
268*9880d681SAndroid Build Coastguard Worker unsigned StartOp = InlineAsm::MIOp_FirstOperand;
269*9880d681SAndroid Build Coastguard Worker
270*9880d681SAndroid Build Coastguard Worker // extracts the registers from the inline assembly instruction
271*9880d681SAndroid Build Coastguard Worker for (unsigned i = StartOp, e = MI.getNumOperands(); i != e; ++i) {
272*9880d681SAndroid Build Coastguard Worker const MachineOperand &MO = MI.getOperand(i);
273*9880d681SAndroid Build Coastguard Worker if (MO.isReg()) {
274*9880d681SAndroid Build Coastguard Worker if (Reg1Index == UNASSIGNED_INDEX)
275*9880d681SAndroid Build Coastguard Worker Reg1Index = MO.getReg();
276*9880d681SAndroid Build Coastguard Worker else if (Reg2Index == UNASSIGNED_INDEX)
277*9880d681SAndroid Build Coastguard Worker Reg2Index = MO.getReg();
278*9880d681SAndroid Build Coastguard Worker else if (Reg3Index == UNASSIGNED_INDEX)
279*9880d681SAndroid Build Coastguard Worker Reg3Index = MO.getReg();
280*9880d681SAndroid Build Coastguard Worker }
281*9880d681SAndroid Build Coastguard Worker if (Reg3Index != UNASSIGNED_INDEX)
282*9880d681SAndroid Build Coastguard Worker break;
283*9880d681SAndroid Build Coastguard Worker }
284*9880d681SAndroid Build Coastguard Worker }
285*9880d681SAndroid Build Coastguard Worker }
286*9880d681SAndroid Build Coastguard Worker
287*9880d681SAndroid Build Coastguard Worker if (Reg1Index != UNASSIGNED_INDEX && Reg2Index != UNASSIGNED_INDEX &&
288*9880d681SAndroid Build Coastguard Worker Reg3Index != UNASSIGNED_INDEX) {
289*9880d681SAndroid Build Coastguard Worker clearUsedRegisterList();
290*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator NMBBI = std::next(MBBI);
291*9880d681SAndroid Build Coastguard Worker // Whatever Reg3Index is hasn't been used yet, so we need to reserve it.
292*9880d681SAndroid Build Coastguard Worker markRegisterUsed(Reg3Index);
293*9880d681SAndroid Build Coastguard Worker const int ScratchReg1Index = getUnusedFPRegister(MF.getRegInfo());
294*9880d681SAndroid Build Coastguard Worker markRegisterUsed(ScratchReg1Index);
295*9880d681SAndroid Build Coastguard Worker const int ScratchReg2Index = getUnusedFPRegister(MF.getRegInfo());
296*9880d681SAndroid Build Coastguard Worker markRegisterUsed(ScratchReg2Index);
297*9880d681SAndroid Build Coastguard Worker
298*9880d681SAndroid Build Coastguard Worker if (ScratchReg1Index == UNASSIGNED_INDEX ||
299*9880d681SAndroid Build Coastguard Worker ScratchReg2Index == UNASSIGNED_INDEX) {
300*9880d681SAndroid Build Coastguard Worker errs() << "Cannot allocate free scratch registers for the "
301*9880d681SAndroid Build Coastguard Worker "ReplaceFMULS pass."
302*9880d681SAndroid Build Coastguard Worker << "\n";
303*9880d681SAndroid Build Coastguard Worker } else {
304*9880d681SAndroid Build Coastguard Worker // create fstod %f20,%f0
305*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD))
306*9880d681SAndroid Build Coastguard Worker .addReg(ScratchReg1Index)
307*9880d681SAndroid Build Coastguard Worker .addReg(Reg1Index);
308*9880d681SAndroid Build Coastguard Worker
309*9880d681SAndroid Build Coastguard Worker // create fstod %f21,%f2
310*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, MBBI, DL, TII.get(SP::FSTOD))
311*9880d681SAndroid Build Coastguard Worker .addReg(ScratchReg2Index)
312*9880d681SAndroid Build Coastguard Worker .addReg(Reg2Index);
313*9880d681SAndroid Build Coastguard Worker
314*9880d681SAndroid Build Coastguard Worker // create fmuld %f0,%f2,%f8
315*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, MBBI, DL, TII.get(SP::FMULD))
316*9880d681SAndroid Build Coastguard Worker .addReg(Reg3Index)
317*9880d681SAndroid Build Coastguard Worker .addReg(ScratchReg1Index)
318*9880d681SAndroid Build Coastguard Worker .addReg(ScratchReg2Index);
319*9880d681SAndroid Build Coastguard Worker
320*9880d681SAndroid Build Coastguard Worker MI.eraseFromParent();
321*9880d681SAndroid Build Coastguard Worker MBBI = NMBBI;
322*9880d681SAndroid Build Coastguard Worker
323*9880d681SAndroid Build Coastguard Worker Modified = true;
324*9880d681SAndroid Build Coastguard Worker }
325*9880d681SAndroid Build Coastguard Worker }
326*9880d681SAndroid Build Coastguard Worker }
327*9880d681SAndroid Build Coastguard Worker }
328*9880d681SAndroid Build Coastguard Worker
329*9880d681SAndroid Build Coastguard Worker return Modified;
330*9880d681SAndroid Build Coastguard Worker }
331*9880d681SAndroid Build Coastguard Worker
332*9880d681SAndroid Build Coastguard Worker //*****************************************************************************
333*9880d681SAndroid Build Coastguard Worker //**** FixAllFDIVSQRT pass
334*9880d681SAndroid Build Coastguard Worker //*****************************************************************************
335*9880d681SAndroid Build Coastguard Worker // This pass fixes the incorrectly working FDIVx and FSQRTx instructions that
336*9880d681SAndroid Build Coastguard Worker // exist for some earlier versions of the LEON processor line. Five NOP
337*9880d681SAndroid Build Coastguard Worker // instructions need to be inserted after these instructions to ensure the
338*9880d681SAndroid Build Coastguard Worker // correct result is placed in the destination registers before they are used.
339*9880d681SAndroid Build Coastguard Worker //
340*9880d681SAndroid Build Coastguard Worker // This pass implements two fixes:
341*9880d681SAndroid Build Coastguard Worker // 1) fixing the FSQRTS and FSQRTD instructions.
342*9880d681SAndroid Build Coastguard Worker // 2) fixing the FDIVS and FDIVD instructions.
343*9880d681SAndroid Build Coastguard Worker //
344*9880d681SAndroid Build Coastguard Worker // FSQRTS and FDIVS are converted to FDIVD and FSQRTD respectively earlier in
345*9880d681SAndroid Build Coastguard Worker // the pipeline when this option is enabled, so this pass needs only to deal
346*9880d681SAndroid Build Coastguard Worker // with the changes that still need implementing for the "double" versions
347*9880d681SAndroid Build Coastguard Worker // of these instructions.
348*9880d681SAndroid Build Coastguard Worker //
349*9880d681SAndroid Build Coastguard Worker char FixAllFDIVSQRT::ID = 0;
350*9880d681SAndroid Build Coastguard Worker
FixAllFDIVSQRT(TargetMachine & tm)351*9880d681SAndroid Build Coastguard Worker FixAllFDIVSQRT::FixAllFDIVSQRT(TargetMachine &tm)
352*9880d681SAndroid Build Coastguard Worker : LEONMachineFunctionPass(tm, ID) {}
353*9880d681SAndroid Build Coastguard Worker
runOnMachineFunction(MachineFunction & MF)354*9880d681SAndroid Build Coastguard Worker bool FixAllFDIVSQRT::runOnMachineFunction(MachineFunction &MF) {
355*9880d681SAndroid Build Coastguard Worker Subtarget = &MF.getSubtarget<SparcSubtarget>();
356*9880d681SAndroid Build Coastguard Worker const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
357*9880d681SAndroid Build Coastguard Worker DebugLoc DL = DebugLoc();
358*9880d681SAndroid Build Coastguard Worker
359*9880d681SAndroid Build Coastguard Worker bool Modified = false;
360*9880d681SAndroid Build Coastguard Worker for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
361*9880d681SAndroid Build Coastguard Worker MachineBasicBlock &MBB = *MFI;
362*9880d681SAndroid Build Coastguard Worker for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
363*9880d681SAndroid Build Coastguard Worker MachineInstr &MI = *MBBI;
364*9880d681SAndroid Build Coastguard Worker unsigned Opcode = MI.getOpcode();
365*9880d681SAndroid Build Coastguard Worker
366*9880d681SAndroid Build Coastguard Worker if (MI.isInlineAsm()) {
367*9880d681SAndroid Build Coastguard Worker StringRef AsmString =
368*9880d681SAndroid Build Coastguard Worker MI.getOperand(InlineAsm::MIOp_AsmString).getSymbolName();
369*9880d681SAndroid Build Coastguard Worker if (AsmString.startswith_lower("fsqrtd")) {
370*9880d681SAndroid Build Coastguard Worker // this is an inline fsqrts instruction
371*9880d681SAndroid Build Coastguard Worker Opcode = SP::FSQRTD;
372*9880d681SAndroid Build Coastguard Worker } else if (AsmString.startswith_lower("fdivd")) {
373*9880d681SAndroid Build Coastguard Worker // this is an inline fsqrts instruction
374*9880d681SAndroid Build Coastguard Worker Opcode = SP::FDIVD;
375*9880d681SAndroid Build Coastguard Worker }
376*9880d681SAndroid Build Coastguard Worker }
377*9880d681SAndroid Build Coastguard Worker
378*9880d681SAndroid Build Coastguard Worker // Note: FDIVS and FSQRTS cannot be generated when this erratum fix is
379*9880d681SAndroid Build Coastguard Worker // switched on so we don't need to check for them here. They will
380*9880d681SAndroid Build Coastguard Worker // already have been converted to FSQRTD or FDIVD earlier in the
381*9880d681SAndroid Build Coastguard Worker // pipeline.
382*9880d681SAndroid Build Coastguard Worker if (Opcode == SP::FSQRTD || Opcode == SP::FDIVD) {
383*9880d681SAndroid Build Coastguard Worker // Insert 5 NOPs before FSQRTD,FDIVD.
384*9880d681SAndroid Build Coastguard Worker for (int InsertedCount = 0; InsertedCount < 5; InsertedCount++)
385*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, MBBI, DL, TII.get(SP::NOP));
386*9880d681SAndroid Build Coastguard Worker
387*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator NMBBI = std::next(MBBI);
388*9880d681SAndroid Build Coastguard Worker // ... and inserting 28 NOPs after FSQRTD,FDIVD.
389*9880d681SAndroid Build Coastguard Worker for (int InsertedCount = 0; InsertedCount < 28; InsertedCount++)
390*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP));
391*9880d681SAndroid Build Coastguard Worker
392*9880d681SAndroid Build Coastguard Worker Modified = true;
393*9880d681SAndroid Build Coastguard Worker }
394*9880d681SAndroid Build Coastguard Worker }
395*9880d681SAndroid Build Coastguard Worker }
396*9880d681SAndroid Build Coastguard Worker
397*9880d681SAndroid Build Coastguard Worker return Modified;
398*9880d681SAndroid Build Coastguard Worker }
399*9880d681SAndroid Build Coastguard Worker
400*9880d681SAndroid Build Coastguard Worker //*****************************************************************************
401*9880d681SAndroid Build Coastguard Worker //**** ReplaceSDIV pass
402*9880d681SAndroid Build Coastguard Worker //*****************************************************************************
403*9880d681SAndroid Build Coastguard Worker // This pass fixes the incorrectly working SDIV instruction that
404*9880d681SAndroid Build Coastguard Worker // exist for some earlier versions of the LEON processor line. The instruction
405*9880d681SAndroid Build Coastguard Worker // is replaced with an SDIVcc instruction instead, which is working.
406*9880d681SAndroid Build Coastguard Worker //
407*9880d681SAndroid Build Coastguard Worker char ReplaceSDIV::ID = 0;
408*9880d681SAndroid Build Coastguard Worker
ReplaceSDIV()409*9880d681SAndroid Build Coastguard Worker ReplaceSDIV::ReplaceSDIV() : LEONMachineFunctionPass(ID) {}
410*9880d681SAndroid Build Coastguard Worker
ReplaceSDIV(TargetMachine & tm)411*9880d681SAndroid Build Coastguard Worker ReplaceSDIV::ReplaceSDIV(TargetMachine &tm) : LEONMachineFunctionPass(tm, ID) {}
412*9880d681SAndroid Build Coastguard Worker
runOnMachineFunction(MachineFunction & MF)413*9880d681SAndroid Build Coastguard Worker bool ReplaceSDIV::runOnMachineFunction(MachineFunction &MF) {
414*9880d681SAndroid Build Coastguard Worker Subtarget = &MF.getSubtarget<SparcSubtarget>();
415*9880d681SAndroid Build Coastguard Worker const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
416*9880d681SAndroid Build Coastguard Worker
417*9880d681SAndroid Build Coastguard Worker bool Modified = false;
418*9880d681SAndroid Build Coastguard Worker for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
419*9880d681SAndroid Build Coastguard Worker MachineBasicBlock &MBB = *MFI;
420*9880d681SAndroid Build Coastguard Worker for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
421*9880d681SAndroid Build Coastguard Worker MachineInstr &MI = *MBBI;
422*9880d681SAndroid Build Coastguard Worker unsigned Opcode = MI.getOpcode();
423*9880d681SAndroid Build Coastguard Worker if (Opcode == SP::SDIVrr) {
424*9880d681SAndroid Build Coastguard Worker MI.setDesc(TII.get(SP::SDIVCCrr));
425*9880d681SAndroid Build Coastguard Worker Modified = true;
426*9880d681SAndroid Build Coastguard Worker } else if (Opcode == SP::SDIVri) {
427*9880d681SAndroid Build Coastguard Worker MI.setDesc(TII.get(SP::SDIVCCri));
428*9880d681SAndroid Build Coastguard Worker Modified = true;
429*9880d681SAndroid Build Coastguard Worker }
430*9880d681SAndroid Build Coastguard Worker }
431*9880d681SAndroid Build Coastguard Worker }
432*9880d681SAndroid Build Coastguard Worker
433*9880d681SAndroid Build Coastguard Worker return Modified;
434*9880d681SAndroid Build Coastguard Worker }
435*9880d681SAndroid Build Coastguard Worker
436*9880d681SAndroid Build Coastguard Worker static RegisterPass<ReplaceSDIV> X("replace-sdiv", "Replase SDIV Pass", false,
437*9880d681SAndroid Build Coastguard Worker false);
438*9880d681SAndroid Build Coastguard Worker
439*9880d681SAndroid Build Coastguard Worker //*****************************************************************************
440*9880d681SAndroid Build Coastguard Worker //**** FixCALL pass
441*9880d681SAndroid Build Coastguard Worker //*****************************************************************************
442*9880d681SAndroid Build Coastguard Worker // This pass restricts the size of the immediate operand of the CALL
443*9880d681SAndroid Build Coastguard Worker // instruction, which can cause problems on some earlier versions of the LEON
444*9880d681SAndroid Build Coastguard Worker // processor, which can interpret some of the call address bits incorrectly.
445*9880d681SAndroid Build Coastguard Worker //
446*9880d681SAndroid Build Coastguard Worker char FixCALL::ID = 0;
447*9880d681SAndroid Build Coastguard Worker
FixCALL(TargetMachine & tm)448*9880d681SAndroid Build Coastguard Worker FixCALL::FixCALL(TargetMachine &tm) : LEONMachineFunctionPass(tm, ID) {}
449*9880d681SAndroid Build Coastguard Worker
runOnMachineFunction(MachineFunction & MF)450*9880d681SAndroid Build Coastguard Worker bool FixCALL::runOnMachineFunction(MachineFunction &MF) {
451*9880d681SAndroid Build Coastguard Worker bool Modified = false;
452*9880d681SAndroid Build Coastguard Worker
453*9880d681SAndroid Build Coastguard Worker for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
454*9880d681SAndroid Build Coastguard Worker MachineBasicBlock &MBB = *MFI;
455*9880d681SAndroid Build Coastguard Worker for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
456*9880d681SAndroid Build Coastguard Worker MachineInstr &MI = *MBBI;
457*9880d681SAndroid Build Coastguard Worker MI.print(errs());
458*9880d681SAndroid Build Coastguard Worker errs() << "\n";
459*9880d681SAndroid Build Coastguard Worker
460*9880d681SAndroid Build Coastguard Worker unsigned Opcode = MI.getOpcode();
461*9880d681SAndroid Build Coastguard Worker if (Opcode == SP::CALL || Opcode == SP::CALLrr) {
462*9880d681SAndroid Build Coastguard Worker unsigned NumOperands = MI.getNumOperands();
463*9880d681SAndroid Build Coastguard Worker for (unsigned OperandIndex = 0; OperandIndex < NumOperands;
464*9880d681SAndroid Build Coastguard Worker OperandIndex++) {
465*9880d681SAndroid Build Coastguard Worker MachineOperand &MO = MI.getOperand(OperandIndex);
466*9880d681SAndroid Build Coastguard Worker if (MO.isImm()) {
467*9880d681SAndroid Build Coastguard Worker int64_t Value = MO.getImm();
468*9880d681SAndroid Build Coastguard Worker MO.setImm(Value & 0x000fffffL);
469*9880d681SAndroid Build Coastguard Worker Modified = true;
470*9880d681SAndroid Build Coastguard Worker break;
471*9880d681SAndroid Build Coastguard Worker }
472*9880d681SAndroid Build Coastguard Worker }
473*9880d681SAndroid Build Coastguard Worker } else if (MI.isInlineAsm()) // inline assembly immediate call
474*9880d681SAndroid Build Coastguard Worker {
475*9880d681SAndroid Build Coastguard Worker StringRef AsmString =
476*9880d681SAndroid Build Coastguard Worker MI.getOperand(InlineAsm::MIOp_AsmString).getSymbolName();
477*9880d681SAndroid Build Coastguard Worker if (AsmString.startswith_lower("call")) {
478*9880d681SAndroid Build Coastguard Worker // this is an inline call instruction
479*9880d681SAndroid Build Coastguard Worker unsigned StartOp = InlineAsm::MIOp_FirstOperand;
480*9880d681SAndroid Build Coastguard Worker
481*9880d681SAndroid Build Coastguard Worker // extracts the registers from the inline assembly instruction
482*9880d681SAndroid Build Coastguard Worker for (unsigned i = StartOp, e = MI.getNumOperands(); i != e; ++i) {
483*9880d681SAndroid Build Coastguard Worker MachineOperand &MO = MI.getOperand(i);
484*9880d681SAndroid Build Coastguard Worker if (MO.isImm()) {
485*9880d681SAndroid Build Coastguard Worker int64_t Value = MO.getImm();
486*9880d681SAndroid Build Coastguard Worker MO.setImm(Value & 0x000fffffL);
487*9880d681SAndroid Build Coastguard Worker Modified = true;
488*9880d681SAndroid Build Coastguard Worker }
489*9880d681SAndroid Build Coastguard Worker }
490*9880d681SAndroid Build Coastguard Worker }
491*9880d681SAndroid Build Coastguard Worker }
492*9880d681SAndroid Build Coastguard Worker }
493*9880d681SAndroid Build Coastguard Worker }
494*9880d681SAndroid Build Coastguard Worker
495*9880d681SAndroid Build Coastguard Worker return Modified;
496*9880d681SAndroid Build Coastguard Worker }
497*9880d681SAndroid Build Coastguard Worker
498*9880d681SAndroid Build Coastguard Worker //*****************************************************************************
499*9880d681SAndroid Build Coastguard Worker //**** IgnoreZeroFlag pass
500*9880d681SAndroid Build Coastguard Worker //*****************************************************************************
501*9880d681SAndroid Build Coastguard Worker // This erratum fix fixes the overflow behavior of SDIVCC and UDIVCC
502*9880d681SAndroid Build Coastguard Worker // instructions that exists on some earlier LEON processors. Where these
503*9880d681SAndroid Build Coastguard Worker // instructions are detected, they are replaced by a sequence that will
504*9880d681SAndroid Build Coastguard Worker // explicitly write the overflow bit flag if this is required.
505*9880d681SAndroid Build Coastguard Worker //
506*9880d681SAndroid Build Coastguard Worker char IgnoreZeroFlag::ID = 0;
507*9880d681SAndroid Build Coastguard Worker
IgnoreZeroFlag(TargetMachine & tm)508*9880d681SAndroid Build Coastguard Worker IgnoreZeroFlag::IgnoreZeroFlag(TargetMachine &tm)
509*9880d681SAndroid Build Coastguard Worker : LEONMachineFunctionPass(tm, ID) {}
510*9880d681SAndroid Build Coastguard Worker
runOnMachineFunction(MachineFunction & MF)511*9880d681SAndroid Build Coastguard Worker bool IgnoreZeroFlag::runOnMachineFunction(MachineFunction &MF) {
512*9880d681SAndroid Build Coastguard Worker Subtarget = &MF.getSubtarget<SparcSubtarget>();
513*9880d681SAndroid Build Coastguard Worker const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
514*9880d681SAndroid Build Coastguard Worker DebugLoc DL = DebugLoc();
515*9880d681SAndroid Build Coastguard Worker
516*9880d681SAndroid Build Coastguard Worker bool Modified = false;
517*9880d681SAndroid Build Coastguard Worker for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
518*9880d681SAndroid Build Coastguard Worker MachineBasicBlock &MBB = *MFI;
519*9880d681SAndroid Build Coastguard Worker for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
520*9880d681SAndroid Build Coastguard Worker MachineInstr &MI = *MBBI;
521*9880d681SAndroid Build Coastguard Worker unsigned Opcode = MI.getOpcode();
522*9880d681SAndroid Build Coastguard Worker if (Opcode == SP::SDIVCCrr || Opcode == SP::SDIVCCri ||
523*9880d681SAndroid Build Coastguard Worker Opcode == SP::UDIVCCrr || Opcode == SP::UDIVCCri) {
524*9880d681SAndroid Build Coastguard Worker
525*9880d681SAndroid Build Coastguard Worker // split the current machine basic block - just after the sdivcc/udivcc
526*9880d681SAndroid Build Coastguard Worker // instruction
527*9880d681SAndroid Build Coastguard Worker // create a label that help us skip the zero flag update (of PSR -
528*9880d681SAndroid Build Coastguard Worker // Processor Status Register)
529*9880d681SAndroid Build Coastguard Worker // if conditions are not met
530*9880d681SAndroid Build Coastguard Worker const BasicBlock *LLVM_BB = MBB.getBasicBlock();
531*9880d681SAndroid Build Coastguard Worker MachineFunction::iterator It =
532*9880d681SAndroid Build Coastguard Worker std::next(MachineFunction::iterator(MBB));
533*9880d681SAndroid Build Coastguard Worker
534*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *dneBB = MF.CreateMachineBasicBlock(LLVM_BB);
535*9880d681SAndroid Build Coastguard Worker MF.insert(It, dneBB);
536*9880d681SAndroid Build Coastguard Worker
537*9880d681SAndroid Build Coastguard Worker // Transfer the remainder of MBB and its successor edges to dneBB.
538*9880d681SAndroid Build Coastguard Worker dneBB->splice(dneBB->begin(), &MBB,
539*9880d681SAndroid Build Coastguard Worker std::next(MachineBasicBlock::iterator(MI)), MBB.end());
540*9880d681SAndroid Build Coastguard Worker dneBB->transferSuccessorsAndUpdatePHIs(&MBB);
541*9880d681SAndroid Build Coastguard Worker
542*9880d681SAndroid Build Coastguard Worker MBB.addSuccessor(dneBB);
543*9880d681SAndroid Build Coastguard Worker
544*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator NextMBBI = std::next(MBBI);
545*9880d681SAndroid Build Coastguard Worker
546*9880d681SAndroid Build Coastguard Worker // bvc - branch if overflow flag not set
547*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, NextMBBI, DL, TII.get(SP::BCOND))
548*9880d681SAndroid Build Coastguard Worker .addMBB(dneBB)
549*9880d681SAndroid Build Coastguard Worker .addImm(SPCC::ICC_VS);
550*9880d681SAndroid Build Coastguard Worker
551*9880d681SAndroid Build Coastguard Worker // bnz - branch if not zero
552*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, NextMBBI, DL, TII.get(SP::BCOND))
553*9880d681SAndroid Build Coastguard Worker .addMBB(dneBB)
554*9880d681SAndroid Build Coastguard Worker .addImm(SPCC::ICC_NE);
555*9880d681SAndroid Build Coastguard Worker
556*9880d681SAndroid Build Coastguard Worker // use the WRPSR (Write Processor State Register) instruction to set the
557*9880d681SAndroid Build Coastguard Worker // zeo flag to 1
558*9880d681SAndroid Build Coastguard Worker // create wr %g0, 1, %psr
559*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, NextMBBI, DL, TII.get(SP::WRPSRri))
560*9880d681SAndroid Build Coastguard Worker .addReg(SP::G0)
561*9880d681SAndroid Build Coastguard Worker .addImm(1);
562*9880d681SAndroid Build Coastguard Worker
563*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, NextMBBI, DL, TII.get(SP::NOP));
564*9880d681SAndroid Build Coastguard Worker
565*9880d681SAndroid Build Coastguard Worker Modified = true;
566*9880d681SAndroid Build Coastguard Worker } else if (MI.isInlineAsm()) {
567*9880d681SAndroid Build Coastguard Worker StringRef AsmString =
568*9880d681SAndroid Build Coastguard Worker MI.getOperand(InlineAsm::MIOp_AsmString).getSymbolName();
569*9880d681SAndroid Build Coastguard Worker if (AsmString.startswith_lower("sdivcc") ||
570*9880d681SAndroid Build Coastguard Worker AsmString.startswith_lower("udivcc")) {
571*9880d681SAndroid Build Coastguard Worker // this is an inline SDIVCC or UDIVCC instruction
572*9880d681SAndroid Build Coastguard Worker
573*9880d681SAndroid Build Coastguard Worker // split the current machine basic block - just after the
574*9880d681SAndroid Build Coastguard Worker // sdivcc/udivcc instruction
575*9880d681SAndroid Build Coastguard Worker // create a label that help us skip the zero flag update (of PSR -
576*9880d681SAndroid Build Coastguard Worker // Processor Status Register)
577*9880d681SAndroid Build Coastguard Worker // if conditions are not met
578*9880d681SAndroid Build Coastguard Worker const BasicBlock *LLVM_BB = MBB.getBasicBlock();
579*9880d681SAndroid Build Coastguard Worker MachineFunction::iterator It =
580*9880d681SAndroid Build Coastguard Worker std::next(MachineFunction::iterator(MBB));
581*9880d681SAndroid Build Coastguard Worker
582*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *dneBB = MF.CreateMachineBasicBlock(LLVM_BB);
583*9880d681SAndroid Build Coastguard Worker MF.insert(It, dneBB);
584*9880d681SAndroid Build Coastguard Worker
585*9880d681SAndroid Build Coastguard Worker // Transfer the remainder of MBB and its successor edges to dneBB.
586*9880d681SAndroid Build Coastguard Worker dneBB->splice(dneBB->begin(), &MBB,
587*9880d681SAndroid Build Coastguard Worker std::next(MachineBasicBlock::iterator(MI)), MBB.end());
588*9880d681SAndroid Build Coastguard Worker dneBB->transferSuccessorsAndUpdatePHIs(&MBB);
589*9880d681SAndroid Build Coastguard Worker
590*9880d681SAndroid Build Coastguard Worker MBB.addSuccessor(dneBB);
591*9880d681SAndroid Build Coastguard Worker
592*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator NextMBBI = std::next(MBBI);
593*9880d681SAndroid Build Coastguard Worker
594*9880d681SAndroid Build Coastguard Worker // bvc - branch if overflow flag not set
595*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, NextMBBI, DL, TII.get(SP::BCOND))
596*9880d681SAndroid Build Coastguard Worker .addMBB(dneBB)
597*9880d681SAndroid Build Coastguard Worker .addImm(SPCC::ICC_VS);
598*9880d681SAndroid Build Coastguard Worker
599*9880d681SAndroid Build Coastguard Worker // bnz - branch if not zero
600*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, NextMBBI, DL, TII.get(SP::BCOND))
601*9880d681SAndroid Build Coastguard Worker .addMBB(dneBB)
602*9880d681SAndroid Build Coastguard Worker .addImm(SPCC::ICC_NE);
603*9880d681SAndroid Build Coastguard Worker
604*9880d681SAndroid Build Coastguard Worker // use the WRPSR (Write Processor State Register) instruction to set
605*9880d681SAndroid Build Coastguard Worker // the zeo flag to 1
606*9880d681SAndroid Build Coastguard Worker // create wr %g0, 1, %psr
607*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, NextMBBI, DL, TII.get(SP::WRPSRri))
608*9880d681SAndroid Build Coastguard Worker .addReg(SP::G0)
609*9880d681SAndroid Build Coastguard Worker .addImm(1);
610*9880d681SAndroid Build Coastguard Worker
611*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, NextMBBI, DL, TII.get(SP::NOP));
612*9880d681SAndroid Build Coastguard Worker
613*9880d681SAndroid Build Coastguard Worker Modified = true;
614*9880d681SAndroid Build Coastguard Worker }
615*9880d681SAndroid Build Coastguard Worker }
616*9880d681SAndroid Build Coastguard Worker }
617*9880d681SAndroid Build Coastguard Worker }
618*9880d681SAndroid Build Coastguard Worker
619*9880d681SAndroid Build Coastguard Worker return Modified;
620*9880d681SAndroid Build Coastguard Worker }
621*9880d681SAndroid Build Coastguard Worker
622*9880d681SAndroid Build Coastguard Worker //*****************************************************************************
623*9880d681SAndroid Build Coastguard Worker //**** InsertNOPDoublePrecision pass
624*9880d681SAndroid Build Coastguard Worker //*****************************************************************************
625*9880d681SAndroid Build Coastguard Worker // This erratum fix for some earlier LEON processors fixes a problem where a
626*9880d681SAndroid Build Coastguard Worker // double precision load will not yield the correct result if used in FMUL,
627*9880d681SAndroid Build Coastguard Worker // FDIV, FADD, FSUB or FSQRT instructions later. If this sequence is detected,
628*9880d681SAndroid Build Coastguard Worker // inserting a NOP between the two instructions will fix the erratum.
629*9880d681SAndroid Build Coastguard Worker // 1.scans the code after register allocation;
630*9880d681SAndroid Build Coastguard Worker // 2.checks for the problem conditions as described in the AT697E erratum
631*9880d681SAndroid Build Coastguard Worker // “Odd-Numbered FPU Register Dependency not Properly Checked in some
632*9880d681SAndroid Build Coastguard Worker // Double-Precision FPU Operations”;
633*9880d681SAndroid Build Coastguard Worker // 3.inserts NOPs if the problem exists.
634*9880d681SAndroid Build Coastguard Worker //
635*9880d681SAndroid Build Coastguard Worker char InsertNOPDoublePrecision::ID = 0;
636*9880d681SAndroid Build Coastguard Worker
InsertNOPDoublePrecision(TargetMachine & tm)637*9880d681SAndroid Build Coastguard Worker InsertNOPDoublePrecision::InsertNOPDoublePrecision(TargetMachine &tm)
638*9880d681SAndroid Build Coastguard Worker : LEONMachineFunctionPass(tm, ID) {}
639*9880d681SAndroid Build Coastguard Worker
runOnMachineFunction(MachineFunction & MF)640*9880d681SAndroid Build Coastguard Worker bool InsertNOPDoublePrecision::runOnMachineFunction(MachineFunction &MF) {
641*9880d681SAndroid Build Coastguard Worker Subtarget = &MF.getSubtarget<SparcSubtarget>();
642*9880d681SAndroid Build Coastguard Worker const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
643*9880d681SAndroid Build Coastguard Worker DebugLoc DL = DebugLoc();
644*9880d681SAndroid Build Coastguard Worker
645*9880d681SAndroid Build Coastguard Worker bool Modified = false;
646*9880d681SAndroid Build Coastguard Worker for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
647*9880d681SAndroid Build Coastguard Worker MachineBasicBlock &MBB = *MFI;
648*9880d681SAndroid Build Coastguard Worker for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
649*9880d681SAndroid Build Coastguard Worker MachineInstr &MI = *MBBI;
650*9880d681SAndroid Build Coastguard Worker unsigned Opcode = MI.getOpcode();
651*9880d681SAndroid Build Coastguard Worker if (Opcode == SP::LDDFri || Opcode == SP::LDDFrr) {
652*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator NMBBI = std::next(MBBI);
653*9880d681SAndroid Build Coastguard Worker MachineInstr &NMI = *NMBBI;
654*9880d681SAndroid Build Coastguard Worker
655*9880d681SAndroid Build Coastguard Worker unsigned NextOpcode = NMI.getOpcode();
656*9880d681SAndroid Build Coastguard Worker // NMI.print(errs());
657*9880d681SAndroid Build Coastguard Worker if (NextOpcode == SP::FADDD || NextOpcode == SP::FSUBD ||
658*9880d681SAndroid Build Coastguard Worker NextOpcode == SP::FMULD || NextOpcode == SP::FDIVD) {
659*9880d681SAndroid Build Coastguard Worker int RegAIndex = GetRegIndexForOperand(MI, 0);
660*9880d681SAndroid Build Coastguard Worker int RegBIndex = GetRegIndexForOperand(NMI, 0);
661*9880d681SAndroid Build Coastguard Worker int RegCIndex =
662*9880d681SAndroid Build Coastguard Worker GetRegIndexForOperand(NMI, 2); // Second source operand is index 2
663*9880d681SAndroid Build Coastguard Worker int RegDIndex =
664*9880d681SAndroid Build Coastguard Worker GetRegIndexForOperand(NMI, 1); // Destination operand is index 1
665*9880d681SAndroid Build Coastguard Worker
666*9880d681SAndroid Build Coastguard Worker if ((RegAIndex == RegBIndex + 1 && RegBIndex == RegDIndex) ||
667*9880d681SAndroid Build Coastguard Worker (RegAIndex == RegCIndex + 1 && RegCIndex == RegDIndex) ||
668*9880d681SAndroid Build Coastguard Worker (RegAIndex == RegBIndex + 1 && RegCIndex == RegDIndex) ||
669*9880d681SAndroid Build Coastguard Worker (RegAIndex == RegCIndex + 1 && RegBIndex == RegDIndex)) {
670*9880d681SAndroid Build Coastguard Worker // Insert NOP between the two instructions.
671*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP));
672*9880d681SAndroid Build Coastguard Worker Modified = true;
673*9880d681SAndroid Build Coastguard Worker }
674*9880d681SAndroid Build Coastguard Worker
675*9880d681SAndroid Build Coastguard Worker // Check the errata patterns that only happen for FADDD and FMULD
676*9880d681SAndroid Build Coastguard Worker if (Modified == false &&
677*9880d681SAndroid Build Coastguard Worker (NextOpcode == SP::FADDD || NextOpcode == SP::FMULD)) {
678*9880d681SAndroid Build Coastguard Worker RegAIndex = GetRegIndexForOperand(MI, 1);
679*9880d681SAndroid Build Coastguard Worker if (RegAIndex == RegBIndex + 1 && RegBIndex == RegCIndex &&
680*9880d681SAndroid Build Coastguard Worker RegBIndex == RegDIndex) {
681*9880d681SAndroid Build Coastguard Worker // Insert NOP between the two instructions.
682*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP));
683*9880d681SAndroid Build Coastguard Worker Modified = true;
684*9880d681SAndroid Build Coastguard Worker }
685*9880d681SAndroid Build Coastguard Worker }
686*9880d681SAndroid Build Coastguard Worker } else if (NextOpcode == SP::FSQRTD) {
687*9880d681SAndroid Build Coastguard Worker int RegAIndex = GetRegIndexForOperand(MI, 1);
688*9880d681SAndroid Build Coastguard Worker int RegBIndex = GetRegIndexForOperand(NMI, 0);
689*9880d681SAndroid Build Coastguard Worker int RegCIndex = GetRegIndexForOperand(NMI, 1);
690*9880d681SAndroid Build Coastguard Worker
691*9880d681SAndroid Build Coastguard Worker if (RegAIndex == RegBIndex + 1 && RegBIndex == RegCIndex) {
692*9880d681SAndroid Build Coastguard Worker // Insert NOP between the two instructions.
693*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP));
694*9880d681SAndroid Build Coastguard Worker Modified = true;
695*9880d681SAndroid Build Coastguard Worker }
696*9880d681SAndroid Build Coastguard Worker }
697*9880d681SAndroid Build Coastguard Worker }
698*9880d681SAndroid Build Coastguard Worker }
699*9880d681SAndroid Build Coastguard Worker }
700*9880d681SAndroid Build Coastguard Worker
701*9880d681SAndroid Build Coastguard Worker return Modified;
702*9880d681SAndroid Build Coastguard Worker }
703*9880d681SAndroid Build Coastguard Worker
704*9880d681SAndroid Build Coastguard Worker //*****************************************************************************
705*9880d681SAndroid Build Coastguard Worker //**** PreventRoundChange pass
706*9880d681SAndroid Build Coastguard Worker //*****************************************************************************
707*9880d681SAndroid Build Coastguard Worker // To prevent any explicit change of the default rounding mode, this pass
708*9880d681SAndroid Build Coastguard Worker // detects any call of the fesetround function and removes this call from the
709*9880d681SAndroid Build Coastguard Worker // list of generated operations.
710*9880d681SAndroid Build Coastguard Worker //
711*9880d681SAndroid Build Coastguard Worker char PreventRoundChange::ID = 0;
712*9880d681SAndroid Build Coastguard Worker
PreventRoundChange(TargetMachine & tm)713*9880d681SAndroid Build Coastguard Worker PreventRoundChange::PreventRoundChange(TargetMachine &tm)
714*9880d681SAndroid Build Coastguard Worker : LEONMachineFunctionPass(tm, ID) {}
715*9880d681SAndroid Build Coastguard Worker
runOnMachineFunction(MachineFunction & MF)716*9880d681SAndroid Build Coastguard Worker bool PreventRoundChange::runOnMachineFunction(MachineFunction &MF) {
717*9880d681SAndroid Build Coastguard Worker Subtarget = &MF.getSubtarget<SparcSubtarget>();
718*9880d681SAndroid Build Coastguard Worker
719*9880d681SAndroid Build Coastguard Worker bool Modified = false;
720*9880d681SAndroid Build Coastguard Worker for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
721*9880d681SAndroid Build Coastguard Worker MachineBasicBlock &MBB = *MFI;
722*9880d681SAndroid Build Coastguard Worker for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
723*9880d681SAndroid Build Coastguard Worker MachineInstr &MI = *MBBI;
724*9880d681SAndroid Build Coastguard Worker unsigned Opcode = MI.getOpcode();
725*9880d681SAndroid Build Coastguard Worker if (Opcode == SP::CALL && MI.getNumOperands() > 0) {
726*9880d681SAndroid Build Coastguard Worker MachineOperand &MO = MI.getOperand(0);
727*9880d681SAndroid Build Coastguard Worker
728*9880d681SAndroid Build Coastguard Worker if (MO.isGlobal()) {
729*9880d681SAndroid Build Coastguard Worker StringRef FuncName = MO.getGlobal()->getName();
730*9880d681SAndroid Build Coastguard Worker if (FuncName.compare_lower("fesetround") == 0) {
731*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator NMBBI = std::next(MBBI);
732*9880d681SAndroid Build Coastguard Worker MI.eraseFromParent();
733*9880d681SAndroid Build Coastguard Worker MBBI = NMBBI;
734*9880d681SAndroid Build Coastguard Worker Modified = true;
735*9880d681SAndroid Build Coastguard Worker }
736*9880d681SAndroid Build Coastguard Worker }
737*9880d681SAndroid Build Coastguard Worker }
738*9880d681SAndroid Build Coastguard Worker }
739*9880d681SAndroid Build Coastguard Worker }
740*9880d681SAndroid Build Coastguard Worker
741*9880d681SAndroid Build Coastguard Worker return Modified;
742*9880d681SAndroid Build Coastguard Worker }
743*9880d681SAndroid Build Coastguard Worker //*****************************************************************************
744*9880d681SAndroid Build Coastguard Worker //**** FlushCacheLineSWAP pass
745*9880d681SAndroid Build Coastguard Worker //*****************************************************************************
746*9880d681SAndroid Build Coastguard Worker // This pass inserts FLUSHW just before any SWAP atomic instruction.
747*9880d681SAndroid Build Coastguard Worker //
748*9880d681SAndroid Build Coastguard Worker char FlushCacheLineSWAP::ID = 0;
749*9880d681SAndroid Build Coastguard Worker
FlushCacheLineSWAP(TargetMachine & tm)750*9880d681SAndroid Build Coastguard Worker FlushCacheLineSWAP::FlushCacheLineSWAP(TargetMachine &tm)
751*9880d681SAndroid Build Coastguard Worker : LEONMachineFunctionPass(tm, ID) {}
752*9880d681SAndroid Build Coastguard Worker
runOnMachineFunction(MachineFunction & MF)753*9880d681SAndroid Build Coastguard Worker bool FlushCacheLineSWAP::runOnMachineFunction(MachineFunction &MF) {
754*9880d681SAndroid Build Coastguard Worker Subtarget = &MF.getSubtarget<SparcSubtarget>();
755*9880d681SAndroid Build Coastguard Worker const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
756*9880d681SAndroid Build Coastguard Worker DebugLoc DL = DebugLoc();
757*9880d681SAndroid Build Coastguard Worker
758*9880d681SAndroid Build Coastguard Worker bool Modified = false;
759*9880d681SAndroid Build Coastguard Worker for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
760*9880d681SAndroid Build Coastguard Worker MachineBasicBlock &MBB = *MFI;
761*9880d681SAndroid Build Coastguard Worker for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
762*9880d681SAndroid Build Coastguard Worker MachineInstr &MI = *MBBI;
763*9880d681SAndroid Build Coastguard Worker unsigned Opcode = MI.getOpcode();
764*9880d681SAndroid Build Coastguard Worker if (Opcode == SP::SWAPrr || Opcode == SP::SWAPri ||
765*9880d681SAndroid Build Coastguard Worker Opcode == SP::LDSTUBrr || Opcode == SP::LDSTUBri) {
766*9880d681SAndroid Build Coastguard Worker // insert flush and 5 NOPs before the swap/ldstub instruction
767*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, MBBI, DL, TII.get(SP::FLUSH));
768*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, MBBI, DL, TII.get(SP::NOP));
769*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, MBBI, DL, TII.get(SP::NOP));
770*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, MBBI, DL, TII.get(SP::NOP));
771*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, MBBI, DL, TII.get(SP::NOP));
772*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, MBBI, DL, TII.get(SP::NOP));
773*9880d681SAndroid Build Coastguard Worker
774*9880d681SAndroid Build Coastguard Worker Modified = true;
775*9880d681SAndroid Build Coastguard Worker } else if (MI.isInlineAsm()) {
776*9880d681SAndroid Build Coastguard Worker StringRef AsmString =
777*9880d681SAndroid Build Coastguard Worker MI.getOperand(InlineAsm::MIOp_AsmString).getSymbolName();
778*9880d681SAndroid Build Coastguard Worker if (AsmString.startswith_lower("swap") ||
779*9880d681SAndroid Build Coastguard Worker AsmString.startswith_lower("ldstub")) {
780*9880d681SAndroid Build Coastguard Worker // this is an inline swap or ldstub instruction
781*9880d681SAndroid Build Coastguard Worker
782*9880d681SAndroid Build Coastguard Worker // insert flush and 5 NOPs before the swap/ldstub instruction
783*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, MBBI, DL, TII.get(SP::FLUSH));
784*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, MBBI, DL, TII.get(SP::NOP));
785*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, MBBI, DL, TII.get(SP::NOP));
786*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, MBBI, DL, TII.get(SP::NOP));
787*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, MBBI, DL, TII.get(SP::NOP));
788*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, MBBI, DL, TII.get(SP::NOP));
789*9880d681SAndroid Build Coastguard Worker
790*9880d681SAndroid Build Coastguard Worker Modified = true;
791*9880d681SAndroid Build Coastguard Worker }
792*9880d681SAndroid Build Coastguard Worker }
793*9880d681SAndroid Build Coastguard Worker }
794*9880d681SAndroid Build Coastguard Worker }
795*9880d681SAndroid Build Coastguard Worker
796*9880d681SAndroid Build Coastguard Worker return Modified;
797*9880d681SAndroid Build Coastguard Worker }
798*9880d681SAndroid Build Coastguard Worker
799*9880d681SAndroid Build Coastguard Worker //*****************************************************************************
800*9880d681SAndroid Build Coastguard Worker //**** InsertNOPsLoadStore pass
801*9880d681SAndroid Build Coastguard Worker //*****************************************************************************
802*9880d681SAndroid Build Coastguard Worker // This pass shall insert NOPs between floating point loads and stores when the
803*9880d681SAndroid Build Coastguard Worker // following circumstances are present [5]:
804*9880d681SAndroid Build Coastguard Worker // Pattern 1:
805*9880d681SAndroid Build Coastguard Worker // 1. single-precision load or single-precision FPOP to register %fX, where X is
806*9880d681SAndroid Build Coastguard Worker // the same register as the store being checked;
807*9880d681SAndroid Build Coastguard Worker // 2. single-precision load or single-precision FPOP to register %fY , where Y
808*9880d681SAndroid Build Coastguard Worker // is the opposite register in the same double-precision pair;
809*9880d681SAndroid Build Coastguard Worker // 3. 0-3 instructions of any kind, except stores from %fX or %fY or operations
810*9880d681SAndroid Build Coastguard Worker // with %fX as destination;
811*9880d681SAndroid Build Coastguard Worker // 4. the store (from register %fX) being considered.
812*9880d681SAndroid Build Coastguard Worker // Pattern 2:
813*9880d681SAndroid Build Coastguard Worker // 1. double-precision FPOP;
814*9880d681SAndroid Build Coastguard Worker // 2. any number of operations on any kind, except no double-precision FPOP and
815*9880d681SAndroid Build Coastguard Worker // at most one (less than two) single-precision or single-to-double FPOPs;
816*9880d681SAndroid Build Coastguard Worker // 3. the store (from register %fX) being considered.
817*9880d681SAndroid Build Coastguard Worker //
818*9880d681SAndroid Build Coastguard Worker char InsertNOPsLoadStore::ID = 0;
819*9880d681SAndroid Build Coastguard Worker
InsertNOPsLoadStore(TargetMachine & tm)820*9880d681SAndroid Build Coastguard Worker InsertNOPsLoadStore::InsertNOPsLoadStore(TargetMachine &tm)
821*9880d681SAndroid Build Coastguard Worker : LEONMachineFunctionPass(tm, ID) {}
822*9880d681SAndroid Build Coastguard Worker
runOnMachineFunction(MachineFunction & MF)823*9880d681SAndroid Build Coastguard Worker bool InsertNOPsLoadStore::runOnMachineFunction(MachineFunction &MF) {
824*9880d681SAndroid Build Coastguard Worker Subtarget = &MF.getSubtarget<SparcSubtarget>();
825*9880d681SAndroid Build Coastguard Worker const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
826*9880d681SAndroid Build Coastguard Worker DebugLoc DL = DebugLoc();
827*9880d681SAndroid Build Coastguard Worker
828*9880d681SAndroid Build Coastguard Worker MachineInstr *Pattern1FirstInstruction = NULL;
829*9880d681SAndroid Build Coastguard Worker MachineInstr *Pattern2FirstInstruction = NULL;
830*9880d681SAndroid Build Coastguard Worker unsigned int StoreInstructionsToCheck = 0;
831*9880d681SAndroid Build Coastguard Worker int FxRegIndex, FyRegIndex;
832*9880d681SAndroid Build Coastguard Worker
833*9880d681SAndroid Build Coastguard Worker bool Modified = false;
834*9880d681SAndroid Build Coastguard Worker for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
835*9880d681SAndroid Build Coastguard Worker MachineBasicBlock &MBB = *MFI;
836*9880d681SAndroid Build Coastguard Worker for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) {
837*9880d681SAndroid Build Coastguard Worker MachineInstr &MI = *MBBI;
838*9880d681SAndroid Build Coastguard Worker
839*9880d681SAndroid Build Coastguard Worker if (StoreInstructionsToCheck > 0) {
840*9880d681SAndroid Build Coastguard Worker if (((MI.getOpcode() == SP::STFrr || MI.getOpcode() == SP::STFri) &&
841*9880d681SAndroid Build Coastguard Worker (GetRegIndexForOperand(MI, LAST_OPERAND) == FxRegIndex ||
842*9880d681SAndroid Build Coastguard Worker GetRegIndexForOperand(MI, LAST_OPERAND) == FyRegIndex)) ||
843*9880d681SAndroid Build Coastguard Worker GetRegIndexForOperand(MI, 0) == FxRegIndex) {
844*9880d681SAndroid Build Coastguard Worker // Insert four NOPs
845*9880d681SAndroid Build Coastguard Worker for (unsigned InsertedCount = 0; InsertedCount < 4; InsertedCount++) {
846*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, MBBI, DL, TII.get(SP::NOP));
847*9880d681SAndroid Build Coastguard Worker }
848*9880d681SAndroid Build Coastguard Worker Modified = true;
849*9880d681SAndroid Build Coastguard Worker }
850*9880d681SAndroid Build Coastguard Worker StoreInstructionsToCheck--;
851*9880d681SAndroid Build Coastguard Worker }
852*9880d681SAndroid Build Coastguard Worker
853*9880d681SAndroid Build Coastguard Worker switch (MI.getOpcode()) {
854*9880d681SAndroid Build Coastguard Worker // Watch for Pattern 1 FPop instructions
855*9880d681SAndroid Build Coastguard Worker case SP::LDrr:
856*9880d681SAndroid Build Coastguard Worker case SP::LDri:
857*9880d681SAndroid Build Coastguard Worker case SP::LDFrr:
858*9880d681SAndroid Build Coastguard Worker case SP::LDFri:
859*9880d681SAndroid Build Coastguard Worker case SP::FADDS:
860*9880d681SAndroid Build Coastguard Worker case SP::FSUBS:
861*9880d681SAndroid Build Coastguard Worker case SP::FMULS:
862*9880d681SAndroid Build Coastguard Worker case SP::FDIVS:
863*9880d681SAndroid Build Coastguard Worker case SP::FSQRTS:
864*9880d681SAndroid Build Coastguard Worker case SP::FCMPS:
865*9880d681SAndroid Build Coastguard Worker case SP::FMOVS:
866*9880d681SAndroid Build Coastguard Worker case SP::FNEGS:
867*9880d681SAndroid Build Coastguard Worker case SP::FABSS:
868*9880d681SAndroid Build Coastguard Worker case SP::FITOS:
869*9880d681SAndroid Build Coastguard Worker case SP::FSTOI:
870*9880d681SAndroid Build Coastguard Worker case SP::FITOD:
871*9880d681SAndroid Build Coastguard Worker case SP::FDTOI:
872*9880d681SAndroid Build Coastguard Worker case SP::FDTOS:
873*9880d681SAndroid Build Coastguard Worker if (Pattern1FirstInstruction != NULL) {
874*9880d681SAndroid Build Coastguard Worker FxRegIndex = GetRegIndexForOperand(*Pattern1FirstInstruction, 0);
875*9880d681SAndroid Build Coastguard Worker FyRegIndex = GetRegIndexForOperand(MI, 0);
876*9880d681SAndroid Build Coastguard Worker
877*9880d681SAndroid Build Coastguard Worker // Check to see if these registers are part of the same double
878*9880d681SAndroid Build Coastguard Worker // precision
879*9880d681SAndroid Build Coastguard Worker // register pair.
880*9880d681SAndroid Build Coastguard Worker int DoublePrecRegIndexForX = (FxRegIndex - SP::F0) / 2;
881*9880d681SAndroid Build Coastguard Worker int DoublePrecRegIndexForY = (FyRegIndex - SP::F0) / 2;
882*9880d681SAndroid Build Coastguard Worker
883*9880d681SAndroid Build Coastguard Worker if (DoublePrecRegIndexForX == DoublePrecRegIndexForY)
884*9880d681SAndroid Build Coastguard Worker StoreInstructionsToCheck = 4;
885*9880d681SAndroid Build Coastguard Worker }
886*9880d681SAndroid Build Coastguard Worker
887*9880d681SAndroid Build Coastguard Worker Pattern1FirstInstruction = &MI;
888*9880d681SAndroid Build Coastguard Worker break;
889*9880d681SAndroid Build Coastguard Worker // End of Pattern 1
890*9880d681SAndroid Build Coastguard Worker
891*9880d681SAndroid Build Coastguard Worker // Search for Pattern 2
892*9880d681SAndroid Build Coastguard Worker case SP::FADDD:
893*9880d681SAndroid Build Coastguard Worker case SP::FSUBD:
894*9880d681SAndroid Build Coastguard Worker case SP::FMULD:
895*9880d681SAndroid Build Coastguard Worker case SP::FDIVD:
896*9880d681SAndroid Build Coastguard Worker case SP::FSQRTD:
897*9880d681SAndroid Build Coastguard Worker case SP::FCMPD:
898*9880d681SAndroid Build Coastguard Worker Pattern2FirstInstruction = &MI;
899*9880d681SAndroid Build Coastguard Worker Pattern1FirstInstruction = NULL;
900*9880d681SAndroid Build Coastguard Worker break;
901*9880d681SAndroid Build Coastguard Worker
902*9880d681SAndroid Build Coastguard Worker case SP::STFrr:
903*9880d681SAndroid Build Coastguard Worker case SP::STFri:
904*9880d681SAndroid Build Coastguard Worker case SP::STDFrr:
905*9880d681SAndroid Build Coastguard Worker case SP::STDFri:
906*9880d681SAndroid Build Coastguard Worker if (Pattern2FirstInstruction != NULL) {
907*9880d681SAndroid Build Coastguard Worker if (GetRegIndexForOperand(MI, LAST_OPERAND) ==
908*9880d681SAndroid Build Coastguard Worker GetRegIndexForOperand(*Pattern2FirstInstruction, 0)) {
909*9880d681SAndroid Build Coastguard Worker // Insert four NOPs
910*9880d681SAndroid Build Coastguard Worker for (unsigned InsertedCount = 0; InsertedCount < 4;
911*9880d681SAndroid Build Coastguard Worker InsertedCount++) {
912*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, MBBI, DL, TII.get(SP::NOP));
913*9880d681SAndroid Build Coastguard Worker }
914*9880d681SAndroid Build Coastguard Worker
915*9880d681SAndroid Build Coastguard Worker Pattern2FirstInstruction = NULL;
916*9880d681SAndroid Build Coastguard Worker }
917*9880d681SAndroid Build Coastguard Worker }
918*9880d681SAndroid Build Coastguard Worker Pattern1FirstInstruction = NULL;
919*9880d681SAndroid Build Coastguard Worker break;
920*9880d681SAndroid Build Coastguard Worker // End of Pattern 2
921*9880d681SAndroid Build Coastguard Worker
922*9880d681SAndroid Build Coastguard Worker default:
923*9880d681SAndroid Build Coastguard Worker // Ensure we don't count debug-only values while we're testing for the
924*9880d681SAndroid Build Coastguard Worker // patterns.
925*9880d681SAndroid Build Coastguard Worker if (!MI.isDebugValue())
926*9880d681SAndroid Build Coastguard Worker Pattern1FirstInstruction = NULL;
927*9880d681SAndroid Build Coastguard Worker break;
928*9880d681SAndroid Build Coastguard Worker }
929*9880d681SAndroid Build Coastguard Worker }
930*9880d681SAndroid Build Coastguard Worker }
931*9880d681SAndroid Build Coastguard Worker
932*9880d681SAndroid Build Coastguard Worker return Modified;
933*9880d681SAndroid Build Coastguard Worker }
934