llvm-6502/lib/Target/Sparc/FPMover.cpp
Devang Patel 3e15bf33e0 Use 'static const char' instead of 'static const int'.
Due to darwin gcc bug, one version of darwin linker coalesces
static const int, which defauts PassID based pass identification.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36652 91177308-0d34-0410-b5e6-96231b3b80d8
2007-05-02 21:39:20 +00:00

139 lines
4.9 KiB
C++

//===-- FPMover.cpp - Sparc double-precision floating point move fixer ----===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Expand FpMOVD/FpABSD/FpNEGD instructions into their single-precision pieces.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "fpmover"
#include "Sparc.h"
#include "SparcSubtarget.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Debug.h"
using namespace llvm;
STATISTIC(NumFpDs , "Number of instructions translated");
STATISTIC(NoopFpDs, "Number of noop instructions removed");
namespace {
struct FPMover : public MachineFunctionPass {
/// Target machine description which we query for reg. names, data
/// layout, etc.
///
TargetMachine &TM;
static const char ID;
FPMover(TargetMachine &tm)
: MachineFunctionPass((intptr_t)&ID), TM(tm) { }
virtual const char *getPassName() const {
return "Sparc Double-FP Move Fixer";
}
bool runOnMachineBasicBlock(MachineBasicBlock &MBB);
bool runOnMachineFunction(MachineFunction &F);
};
const char FPMover::ID = 0;
} // end of anonymous namespace
/// createSparcFPMoverPass - Returns a pass that turns FpMOVD
/// instructions into FMOVS instructions
///
FunctionPass *llvm::createSparcFPMoverPass(TargetMachine &tm) {
return new FPMover(tm);
}
/// getDoubleRegPair - Given a DFP register, return the even and odd FP
/// registers that correspond to it.
static void getDoubleRegPair(unsigned DoubleReg, unsigned &EvenReg,
unsigned &OddReg) {
static const unsigned EvenHalvesOfPairs[] = {
SP::F0, SP::F2, SP::F4, SP::F6, SP::F8, SP::F10, SP::F12, SP::F14,
SP::F16, SP::F18, SP::F20, SP::F22, SP::F24, SP::F26, SP::F28, SP::F30
};
static const unsigned OddHalvesOfPairs[] = {
SP::F1, SP::F3, SP::F5, SP::F7, SP::F9, SP::F11, SP::F13, SP::F15,
SP::F17, SP::F19, SP::F21, SP::F23, SP::F25, SP::F27, SP::F29, SP::F31
};
static const unsigned DoubleRegsInOrder[] = {
SP::D0, SP::D1, SP::D2, SP::D3, SP::D4, SP::D5, SP::D6, SP::D7, SP::D8,
SP::D9, SP::D10, SP::D11, SP::D12, SP::D13, SP::D14, SP::D15
};
for (unsigned i = 0; i < sizeof(DoubleRegsInOrder)/sizeof(unsigned); ++i)
if (DoubleRegsInOrder[i] == DoubleReg) {
EvenReg = EvenHalvesOfPairs[i];
OddReg = OddHalvesOfPairs[i];
return;
}
assert(0 && "Can't find reg");
}
/// runOnMachineBasicBlock - Fixup FpMOVD instructions in this MBB.
///
bool FPMover::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
bool Changed = false;
for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ) {
MachineInstr *MI = I++;
if (MI->getOpcode() == SP::FpMOVD || MI->getOpcode() == SP::FpABSD ||
MI->getOpcode() == SP::FpNEGD) {
Changed = true;
unsigned DestDReg = MI->getOperand(0).getReg();
unsigned SrcDReg = MI->getOperand(1).getReg();
if (DestDReg == SrcDReg && MI->getOpcode() == SP::FpMOVD) {
MBB.erase(MI); // Eliminate the noop copy.
++NoopFpDs;
continue;
}
unsigned EvenSrcReg = 0, OddSrcReg = 0, EvenDestReg = 0, OddDestReg = 0;
getDoubleRegPair(DestDReg, EvenDestReg, OddDestReg);
getDoubleRegPair(SrcDReg, EvenSrcReg, OddSrcReg);
const TargetInstrInfo *TII = TM.getInstrInfo();
if (MI->getOpcode() == SP::FpMOVD)
MI->setInstrDescriptor(TII->get(SP::FMOVS));
else if (MI->getOpcode() == SP::FpNEGD)
MI->setInstrDescriptor(TII->get(SP::FNEGS));
else if (MI->getOpcode() == SP::FpABSD)
MI->setInstrDescriptor(TII->get(SP::FABSS));
else
assert(0 && "Unknown opcode!");
MI->getOperand(0).setReg(EvenDestReg);
MI->getOperand(1).setReg(EvenSrcReg);
DOUT << "FPMover: the modified instr is: " << *MI;
// Insert copy for the other half of the double.
if (DestDReg != SrcDReg) {
MI = BuildMI(MBB, I, TM.getInstrInfo()->get(SP::FMOVS), OddDestReg)
.addReg(OddSrcReg);
DOUT << "FPMover: the inserted instr is: " << *MI;
}
++NumFpDs;
}
}
return Changed;
}
bool FPMover::runOnMachineFunction(MachineFunction &F) {
// If the target has V9 instructions, the fp-mover pseudos will never be
// emitted. Avoid a scan of the instructions to improve compile time.
if (TM.getSubtarget<SparcSubtarget>().isV9())
return false;
bool Changed = false;
for (MachineFunction::iterator FI = F.begin(), FE = F.end();
FI != FE; ++FI)
Changed |= runOnMachineBasicBlock(*FI);
return Changed;
}