1 //===-- FPMover.cpp - Sparc double-precision floating point move fixer ----===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Expand FpMOVD/FpABSD/FpNEGD instructions into their single-precision pieces.
12 //===----------------------------------------------------------------------===//
14 #define DEBUG_TYPE "fpmover"
16 #include "SparcSubtarget.h"
17 #include "llvm/CodeGen/MachineFunctionPass.h"
18 #include "llvm/CodeGen/MachineInstrBuilder.h"
19 #include "llvm/Target/TargetMachine.h"
20 #include "llvm/Target/TargetInstrInfo.h"
21 #include "llvm/ADT/Statistic.h"
22 #include "llvm/Support/Debug.h"
23 #include "llvm/Support/ErrorHandling.h"
24 #include "llvm/Support/raw_ostream.h"
27 STATISTIC(NumFpDs
, "Number of instructions translated");
28 STATISTIC(NoopFpDs
, "Number of noop instructions removed");
31 struct FPMover
: public MachineFunctionPass
{
32 /// Target machine description which we query for reg. names, data
38 explicit FPMover(TargetMachine
&tm
)
39 : MachineFunctionPass(&ID
), TM(tm
) { }
41 virtual const char *getPassName() const {
42 return "Sparc Double-FP Move Fixer";
45 bool runOnMachineBasicBlock(MachineBasicBlock
&MBB
);
46 bool runOnMachineFunction(MachineFunction
&F
);
49 } // end of anonymous namespace
51 /// createSparcFPMoverPass - Returns a pass that turns FpMOVD
52 /// instructions into FMOVS instructions
54 FunctionPass
*llvm::createSparcFPMoverPass(TargetMachine
&tm
) {
55 return new FPMover(tm
);
58 /// getDoubleRegPair - Given a DFP register, return the even and odd FP
59 /// registers that correspond to it.
60 static void getDoubleRegPair(unsigned DoubleReg
, unsigned &EvenReg
,
62 static const unsigned EvenHalvesOfPairs
[] = {
63 SP::F0
, SP::F2
, SP::F4
, SP::F6
, SP::F8
, SP::F10
, SP::F12
, SP::F14
,
64 SP::F16
, SP::F18
, SP::F20
, SP::F22
, SP::F24
, SP::F26
, SP::F28
, SP::F30
66 static const unsigned OddHalvesOfPairs
[] = {
67 SP::F1
, SP::F3
, SP::F5
, SP::F7
, SP::F9
, SP::F11
, SP::F13
, SP::F15
,
68 SP::F17
, SP::F19
, SP::F21
, SP::F23
, SP::F25
, SP::F27
, SP::F29
, SP::F31
70 static const unsigned DoubleRegsInOrder
[] = {
71 SP::D0
, SP::D1
, SP::D2
, SP::D3
, SP::D4
, SP::D5
, SP::D6
, SP::D7
, SP::D8
,
72 SP::D9
, SP::D10
, SP::D11
, SP::D12
, SP::D13
, SP::D14
, SP::D15
74 for (unsigned i
= 0; i
< sizeof(DoubleRegsInOrder
)/sizeof(unsigned); ++i
)
75 if (DoubleRegsInOrder
[i
] == DoubleReg
) {
76 EvenReg
= EvenHalvesOfPairs
[i
];
77 OddReg
= OddHalvesOfPairs
[i
];
80 llvm_unreachable("Can't find reg");
83 /// runOnMachineBasicBlock - Fixup FpMOVD instructions in this MBB.
85 bool FPMover::runOnMachineBasicBlock(MachineBasicBlock
&MBB
) {
87 for (MachineBasicBlock::iterator I
= MBB
.begin(); I
!= MBB
.end(); ) {
88 MachineInstr
*MI
= I
++;
89 DebugLoc dl
= MI
->getDebugLoc();
90 if (MI
->getOpcode() == SP::FpMOVD
|| MI
->getOpcode() == SP::FpABSD
||
91 MI
->getOpcode() == SP::FpNEGD
) {
93 unsigned DestDReg
= MI
->getOperand(0).getReg();
94 unsigned SrcDReg
= MI
->getOperand(1).getReg();
95 if (DestDReg
== SrcDReg
&& MI
->getOpcode() == SP::FpMOVD
) {
96 MBB
.erase(MI
); // Eliminate the noop copy.
101 unsigned EvenSrcReg
= 0, OddSrcReg
= 0, EvenDestReg
= 0, OddDestReg
= 0;
102 getDoubleRegPair(DestDReg
, EvenDestReg
, OddDestReg
);
103 getDoubleRegPair(SrcDReg
, EvenSrcReg
, OddSrcReg
);
105 const TargetInstrInfo
*TII
= TM
.getInstrInfo();
106 if (MI
->getOpcode() == SP::FpMOVD
)
107 MI
->setDesc(TII
->get(SP::FMOVS
));
108 else if (MI
->getOpcode() == SP::FpNEGD
)
109 MI
->setDesc(TII
->get(SP::FNEGS
));
110 else if (MI
->getOpcode() == SP::FpABSD
)
111 MI
->setDesc(TII
->get(SP::FABSS
));
113 llvm_unreachable("Unknown opcode!");
115 MI
->getOperand(0).setReg(EvenDestReg
);
116 MI
->getOperand(1).setReg(EvenSrcReg
);
117 DEBUG(errs() << "FPMover: the modified instr is: " << *MI
);
118 // Insert copy for the other half of the double.
119 if (DestDReg
!= SrcDReg
) {
120 MI
= BuildMI(MBB
, I
, dl
, TM
.getInstrInfo()->get(SP::FMOVS
), OddDestReg
)
122 DEBUG(errs() << "FPMover: the inserted instr is: " << *MI
);
130 bool FPMover::runOnMachineFunction(MachineFunction
&F
) {
131 // If the target has V9 instructions, the fp-mover pseudos will never be
132 // emitted. Avoid a scan of the instructions to improve compile time.
133 if (TM
.getSubtarget
<SparcSubtarget
>().isV9())
136 bool Changed
= false;
137 for (MachineFunction::iterator FI
= F
.begin(), FE
= F
.end();
139 Changed
|= runOnMachineBasicBlock(*FI
);