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