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