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"
25 STATISTIC(NumFpDs
, "Number of instructions translated");
26 STATISTIC(NoopFpDs
, "Number of noop instructions removed");
29 struct FPMover
: public MachineFunctionPass
{
30 /// Target machine description which we query for reg. names, data
36 explicit FPMover(TargetMachine
&tm
)
37 : MachineFunctionPass(&ID
), TM(tm
) { }
39 virtual const char *getPassName() const {
40 return "Sparc Double-FP Move Fixer";
43 bool runOnMachineBasicBlock(MachineBasicBlock
&MBB
);
44 bool runOnMachineFunction(MachineFunction
&F
);
47 } // end of anonymous namespace
49 /// createSparcFPMoverPass - Returns a pass that turns FpMOVD
50 /// instructions into FMOVS instructions
52 FunctionPass
*llvm::createSparcFPMoverPass(TargetMachine
&tm
) {
53 return new FPMover(tm
);
56 /// getDoubleRegPair - Given a DFP register, return the even and odd FP
57 /// registers that correspond to it.
58 static void getDoubleRegPair(unsigned DoubleReg
, unsigned &EvenReg
,
60 static const unsigned EvenHalvesOfPairs
[] = {
61 SP::F0
, SP::F2
, SP::F4
, SP::F6
, SP::F8
, SP::F10
, SP::F12
, SP::F14
,
62 SP::F16
, SP::F18
, SP::F20
, SP::F22
, SP::F24
, SP::F26
, SP::F28
, SP::F30
64 static const unsigned OddHalvesOfPairs
[] = {
65 SP::F1
, SP::F3
, SP::F5
, SP::F7
, SP::F9
, SP::F11
, SP::F13
, SP::F15
,
66 SP::F17
, SP::F19
, SP::F21
, SP::F23
, SP::F25
, SP::F27
, SP::F29
, SP::F31
68 static const unsigned DoubleRegsInOrder
[] = {
69 SP::D0
, SP::D1
, SP::D2
, SP::D3
, SP::D4
, SP::D5
, SP::D6
, SP::D7
, SP::D8
,
70 SP::D9
, SP::D10
, SP::D11
, SP::D12
, SP::D13
, SP::D14
, SP::D15
72 for (unsigned i
= 0; i
< sizeof(DoubleRegsInOrder
)/sizeof(unsigned); ++i
)
73 if (DoubleRegsInOrder
[i
] == DoubleReg
) {
74 EvenReg
= EvenHalvesOfPairs
[i
];
75 OddReg
= OddHalvesOfPairs
[i
];
78 assert(0 && "Can't find reg");
81 /// runOnMachineBasicBlock - Fixup FpMOVD instructions in this MBB.
83 bool FPMover::runOnMachineBasicBlock(MachineBasicBlock
&MBB
) {
85 for (MachineBasicBlock::iterator I
= MBB
.begin(); I
!= MBB
.end(); ) {
86 MachineInstr
*MI
= I
++;
87 DebugLoc dl
= MI
->getDebugLoc();
88 if (MI
->getOpcode() == SP::FpMOVD
|| MI
->getOpcode() == SP::FpABSD
||
89 MI
->getOpcode() == SP::FpNEGD
) {
91 unsigned DestDReg
= MI
->getOperand(0).getReg();
92 unsigned SrcDReg
= MI
->getOperand(1).getReg();
93 if (DestDReg
== SrcDReg
&& MI
->getOpcode() == SP::FpMOVD
) {
94 MBB
.erase(MI
); // Eliminate the noop copy.
99 unsigned EvenSrcReg
= 0, OddSrcReg
= 0, EvenDestReg
= 0, OddDestReg
= 0;
100 getDoubleRegPair(DestDReg
, EvenDestReg
, OddDestReg
);
101 getDoubleRegPair(SrcDReg
, EvenSrcReg
, OddSrcReg
);
103 const TargetInstrInfo
*TII
= TM
.getInstrInfo();
104 if (MI
->getOpcode() == SP::FpMOVD
)
105 MI
->setDesc(TII
->get(SP::FMOVS
));
106 else if (MI
->getOpcode() == SP::FpNEGD
)
107 MI
->setDesc(TII
->get(SP::FNEGS
));
108 else if (MI
->getOpcode() == SP::FpABSD
)
109 MI
->setDesc(TII
->get(SP::FABSS
));
111 assert(0 && "Unknown opcode!");
113 MI
->getOperand(0).setReg(EvenDestReg
);
114 MI
->getOperand(1).setReg(EvenSrcReg
);
115 DOUT
<< "FPMover: the modified instr is: " << *MI
;
116 // Insert copy for the other half of the double.
117 if (DestDReg
!= SrcDReg
) {
118 MI
= BuildMI(MBB
, I
, dl
, TM
.getInstrInfo()->get(SP::FMOVS
), OddDestReg
)
120 DOUT
<< "FPMover: the inserted instr is: " << *MI
;
128 bool FPMover::runOnMachineFunction(MachineFunction
&F
) {
129 // If the target has V9 instructions, the fp-mover pseudos will never be
130 // emitted. Avoid a scan of the instructions to improve compile time.
131 if (TM
.getSubtarget
<SparcSubtarget
>().isV9())
134 bool Changed
= false;
135 for (MachineFunction::iterator FI
= F
.begin(), FE
= F
.end();
137 Changed
|= runOnMachineBasicBlock(*FI
);