blob: e8393c53dd83d3e7a936e12cda680ae79f2825d9 [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;
Owen Anderson90c579d2010-08-06 18:33:48 +000027 NEONMoveFixPass() : MachineFunctionPass(ID) {}
Anton Korobeynikov7aaf94b2009-11-03 01:04:26 +000028
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;
Evan Cheng6557bce2011-02-22 19:53:14 +000038 bool isA8;
Anton Korobeynikov7aaf94b2009-11-03 01:04:26 +000039
40 typedef DenseMap<unsigned, const MachineInstr*> RegMap;
41
42 bool InsertMoves(MachineBasicBlock &MBB);
43 };
44 char NEONMoveFixPass::ID = 0;
45}
46
Evan Cheng6557bce2011-02-22 19:53:14 +000047static bool inNEONDomain(unsigned Domain, bool isA8) {
48 if (Domain & ARMII::DomainNEON) {
49 // Some instructions only go down NEON pipeline when executed on CortexA8.
50 if (Domain & ARMII::DomainNEONA8)
51 return isA8;
52 return true;
53 }
54 return false;
55}
56
Anton Korobeynikov7aaf94b2009-11-03 01:04:26 +000057bool NEONMoveFixPass::InsertMoves(MachineBasicBlock &MBB) {
58 RegMap Defs;
59 bool Modified = false;
60
61 // Walk over MBB tracking the def points of the registers.
62 MachineBasicBlock::iterator MII = MBB.begin(), E = MBB.end();
63 MachineBasicBlock::iterator NextMII;
64 for (; MII != E; MII = NextMII) {
Chris Lattner7896c9f2009-12-03 00:50:42 +000065 NextMII = llvm::next(MII);
Anton Korobeynikov7aaf94b2009-11-03 01:04:26 +000066 MachineInstr *MI = &*MII;
67
Jim Grosbache5165492009-11-09 00:11:35 +000068 if (MI->getOpcode() == ARM::VMOVD &&
Anton Korobeynikov7aaf94b2009-11-03 01:04:26 +000069 !TII->isPredicated(MI)) {
70 unsigned SrcReg = MI->getOperand(1).getReg();
Jim Grosbache5165492009-11-09 00:11:35 +000071 // If we do not find an instruction defining the reg, this means the
Anton Korobeynikov7aaf94b2009-11-03 01:04:26 +000072 // register should be live-in for this BB. It's always to better to use
73 // NEON reg-reg moves.
74 unsigned Domain = ARMII::DomainNEON;
75 RegMap::iterator DefMI = Defs.find(SrcReg);
76 if (DefMI != Defs.end()) {
77 Domain = DefMI->second->getDesc().TSFlags & ARMII::DomainMask;
78 // Instructions in general domain are subreg accesses.
79 // Map them to NEON reg-reg moves.
80 if (Domain == ARMII::DomainGeneral)
81 Domain = ARMII::DomainNEON;
82 }
83
Evan Cheng6557bce2011-02-22 19:53:14 +000084 if (inNEONDomain(Domain, isA8)) {
Jim Grosbache5165492009-11-09 00:11:35 +000085 // Convert VMOVD to VMOVDneon
Anton Korobeynikov7aaf94b2009-11-03 01:04:26 +000086 unsigned DestReg = MI->getOperand(0).getReg();
87
88 DEBUG({errs() << "vmov convert: "; MI->dump();});
89
90 // It's safe to ignore imp-defs / imp-uses here, since:
91 // - We're running late, no intelligent condegen passes should be run
92 // afterwards
93 // - The imp-defs / imp-uses are superregs only, we don't care about
94 // them.
Evan Chengac0869d2009-11-21 06:21:52 +000095 AddDefaultPred(BuildMI(MBB, *MI, MI->getDebugLoc(),
96 TII->get(ARM::VMOVDneon), DestReg).addReg(SrcReg));
Anton Korobeynikov7aaf94b2009-11-03 01:04:26 +000097 MBB.erase(MI);
98 MachineBasicBlock::iterator I = prior(NextMII);
99 MI = &*I;
100
101 DEBUG({errs() << " into: "; MI->dump();});
102
103 Modified = true;
104 ++NumVMovs;
105 } else {
Anton Korobeynikov747409a2009-11-03 18:46:11 +0000106 assert((Domain & ARMII::DomainVFP) && "Invalid domain!");
Anton Korobeynikov7aaf94b2009-11-03 01:04:26 +0000107 // Do nothing.
108 }
109 }
110
111 // Update def information.
112 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
113 const MachineOperand& MO = MI->getOperand(i);
114 if (!MO.isReg() || !MO.isDef())
115 continue;
116 unsigned MOReg = MO.getReg();
117
118 Defs[MOReg] = MI;
Jakob Stoklund Olesenfca3a252010-07-06 23:26:23 +0000119 // Catch aliases as well.
120 for (const unsigned *R = TRI->getAliasSet(MOReg); *R; ++R)
Anton Korobeynikov7aaf94b2009-11-03 01:04:26 +0000121 Defs[*R] = MI;
122 }
123 }
124
125 return Modified;
126}
127
128bool NEONMoveFixPass::runOnMachineFunction(MachineFunction &Fn) {
129 ARMFunctionInfo *AFI = Fn.getInfo<ARMFunctionInfo>();
130 const TargetMachine &TM = Fn.getTarget();
131
Evan Cheng9c207ac2010-05-17 01:11:46 +0000132 if (AFI->isThumb1OnlyFunction())
Anton Korobeynikov7aaf94b2009-11-03 01:04:26 +0000133 return false;
134
135 TRI = TM.getRegisterInfo();
Anton Korobeynikov7aaf94b2009-11-03 01:04:26 +0000136 TII = static_cast<const ARMBaseInstrInfo*>(TM.getInstrInfo());
Evan Cheng6557bce2011-02-22 19:53:14 +0000137 isA8 = TM.getSubtarget<ARMSubtarget>().isCortexA8();
Anton Korobeynikov7aaf94b2009-11-03 01:04:26 +0000138
139 bool Modified = false;
140 for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
141 ++MFI) {
142 MachineBasicBlock &MBB = *MFI;
143 Modified |= InsertMoves(MBB);
144 }
145
146 return Modified;
147}
148
149/// createNEONMoveFixPass - Returns an instance of the NEON reg-reg moves fix
150/// pass.
151FunctionPass *llvm::createNEONMoveFixPass() {
152 return new NEONMoveFixPass();
153}