blob: 3c3b9520ca14ab07d7df4d87fc93918b011df7f9 [file] [log] [blame]
Anton Korobeynikov7aaf94b2009-11-03 01:04:26 +00001//===-- NEONMoveFix.cpp - Convert vfp reg-reg moves into neon ---*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#define DEBUG_TYPE "neon-mov-fix"
11#include "ARM.h"
12#include "ARMMachineFunctionInfo.h"
13#include "ARMInstrInfo.h"
14#include "llvm/CodeGen/MachineInstr.h"
15#include "llvm/CodeGen/MachineInstrBuilder.h"
16#include "llvm/CodeGen/MachineFunctionPass.h"
17#include "llvm/ADT/Statistic.h"
18#include "llvm/Support/Debug.h"
19#include "llvm/Support/raw_ostream.h"
20using namespace llvm;
21
22STATISTIC(NumVMovs, "Number of reg-reg moves converted");
23
24namespace {
25 struct NEONMoveFixPass : public MachineFunctionPass {
26 static char ID;
27 NEONMoveFixPass() : MachineFunctionPass(&ID) {}
28
29 virtual bool runOnMachineFunction(MachineFunction &Fn);
30
31 virtual const char *getPassName() const {
32 return "NEON reg-reg move conversion";
33 }
34
35 private:
36 const TargetRegisterInfo *TRI;
37 const ARMBaseInstrInfo *TII;
38 const ARMSubtarget *Subtarget;
39
40 typedef DenseMap<unsigned, const MachineInstr*> RegMap;
41
42 bool InsertMoves(MachineBasicBlock &MBB);
43 };
44 char NEONMoveFixPass::ID = 0;
45}
46
47bool NEONMoveFixPass::InsertMoves(MachineBasicBlock &MBB) {
48 RegMap Defs;
49 bool Modified = false;
50
51 // Walk over MBB tracking the def points of the registers.
52 MachineBasicBlock::iterator MII = MBB.begin(), E = MBB.end();
53 MachineBasicBlock::iterator NextMII;
54 for (; MII != E; MII = NextMII) {
55 NextMII = next(MII);
56 MachineInstr *MI = &*MII;
57
58 if (MI->getOpcode() == ARM::FCPYD &&
59 !TII->isPredicated(MI)) {
60 unsigned SrcReg = MI->getOperand(1).getReg();
61 // If we do not found an instruction defining the reg, this means the
62 // register should be live-in for this BB. It's always to better to use
63 // NEON reg-reg moves.
64 unsigned Domain = ARMII::DomainNEON;
65 RegMap::iterator DefMI = Defs.find(SrcReg);
66 if (DefMI != Defs.end()) {
67 Domain = DefMI->second->getDesc().TSFlags & ARMII::DomainMask;
68 // Instructions in general domain are subreg accesses.
69 // Map them to NEON reg-reg moves.
70 if (Domain == ARMII::DomainGeneral)
71 Domain = ARMII::DomainNEON;
72 }
73
74 if ((Domain & ARMII::DomainNEON) && Subtarget->hasNEON()) {
75 // Convert FCPYD to VMOVD.
76 unsigned DestReg = MI->getOperand(0).getReg();
77
78 DEBUG({errs() << "vmov convert: "; MI->dump();});
79
80 // It's safe to ignore imp-defs / imp-uses here, since:
81 // - We're running late, no intelligent condegen passes should be run
82 // afterwards
83 // - The imp-defs / imp-uses are superregs only, we don't care about
84 // them.
85 BuildMI(MBB, *MI, MI->getDebugLoc(),
86 TII->get(ARM::VMOVD), DestReg).addReg(SrcReg);
87 MBB.erase(MI);
88 MachineBasicBlock::iterator I = prior(NextMII);
89 MI = &*I;
90
91 DEBUG({errs() << " into: "; MI->dump();});
92
93 Modified = true;
94 ++NumVMovs;
95 } else {
96 assert((Domain & ARMII::DomainVFP ||
97 !Subtarget->hasNEON()) && "Invalid domain!");
98 // Do nothing.
99 }
100 }
101
102 // Update def information.
103 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
104 const MachineOperand& MO = MI->getOperand(i);
105 if (!MO.isReg() || !MO.isDef())
106 continue;
107 unsigned MOReg = MO.getReg();
108
109 Defs[MOReg] = MI;
110 // Catch subregs as well.
111 for (const unsigned *R = TRI->getSubRegisters(MOReg); *R; ++R)
112 Defs[*R] = MI;
113 }
114 }
115
116 return Modified;
117}
118
119bool NEONMoveFixPass::runOnMachineFunction(MachineFunction &Fn) {
120 ARMFunctionInfo *AFI = Fn.getInfo<ARMFunctionInfo>();
121 const TargetMachine &TM = Fn.getTarget();
122
123 if (AFI->isThumbFunction())
124 return false;
125
126 TRI = TM.getRegisterInfo();
127 Subtarget = &TM.getSubtarget<ARMSubtarget>();
128 TII = static_cast<const ARMBaseInstrInfo*>(TM.getInstrInfo());
129
130 bool Modified = false;
131 for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
132 ++MFI) {
133 MachineBasicBlock &MBB = *MFI;
134 Modified |= InsertMoves(MBB);
135 }
136
137 return Modified;
138}
139
140/// createNEONMoveFixPass - Returns an instance of the NEON reg-reg moves fix
141/// pass.
142FunctionPass *llvm::createNEONMoveFixPass() {
143 return new NEONMoveFixPass();
144}