blob: bd8c882afed903bdd32856508e624f985f68e270 [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);
Jakob Stoklund Olesenfe428082011-07-29 00:27:35 +000043
44 void TransferImpOps(MachineInstr &Old, MachineInstr &New);
Anton Korobeynikov7aaf94b2009-11-03 01:04:26 +000045 };
46 char NEONMoveFixPass::ID = 0;
47}
48
Evan Cheng6557bce2011-02-22 19:53:14 +000049static bool inNEONDomain(unsigned Domain, bool isA8) {
Evan Cheng2b943562011-02-23 02:35:33 +000050 return (Domain & ARMII::DomainNEON) ||
51 (isA8 && (Domain & ARMII::DomainNEONA8));
Evan Cheng6557bce2011-02-22 19:53:14 +000052}
53
Jakob Stoklund Olesenfe428082011-07-29 00:27:35 +000054/// Transfer implicit kill and def operands from Old to New.
55void NEONMoveFixPass::TransferImpOps(MachineInstr &Old, MachineInstr &New) {
56 for (unsigned i = 0, e = Old.getNumOperands(); i != e; ++i) {
57 MachineOperand &MO = Old.getOperand(i);
58 if (!MO.isReg() || !MO.isImplicit())
59 continue;
60 New.addOperand(MO);
61 }
62}
63
Anton Korobeynikov7aaf94b2009-11-03 01:04:26 +000064bool NEONMoveFixPass::InsertMoves(MachineBasicBlock &MBB) {
65 RegMap Defs;
66 bool Modified = false;
67
68 // Walk over MBB tracking the def points of the registers.
69 MachineBasicBlock::iterator MII = MBB.begin(), E = MBB.end();
70 MachineBasicBlock::iterator NextMII;
71 for (; MII != E; MII = NextMII) {
Chris Lattner7896c9f2009-12-03 00:50:42 +000072 NextMII = llvm::next(MII);
Anton Korobeynikov7aaf94b2009-11-03 01:04:26 +000073 MachineInstr *MI = &*MII;
74
Jim Grosbache5165492009-11-09 00:11:35 +000075 if (MI->getOpcode() == ARM::VMOVD &&
Anton Korobeynikov7aaf94b2009-11-03 01:04:26 +000076 !TII->isPredicated(MI)) {
77 unsigned SrcReg = MI->getOperand(1).getReg();
Jim Grosbache5165492009-11-09 00:11:35 +000078 // If we do not find an instruction defining the reg, this means the
Anton Korobeynikov7aaf94b2009-11-03 01:04:26 +000079 // register should be live-in for this BB. It's always to better to use
80 // NEON reg-reg moves.
81 unsigned Domain = ARMII::DomainNEON;
82 RegMap::iterator DefMI = Defs.find(SrcReg);
83 if (DefMI != Defs.end()) {
84 Domain = DefMI->second->getDesc().TSFlags & ARMII::DomainMask;
85 // Instructions in general domain are subreg accesses.
86 // Map them to NEON reg-reg moves.
87 if (Domain == ARMII::DomainGeneral)
88 Domain = ARMII::DomainNEON;
89 }
90
Evan Cheng6557bce2011-02-22 19:53:14 +000091 if (inNEONDomain(Domain, isA8)) {
Owen Anderson43967a92011-07-15 18:46:47 +000092 // Convert VMOVD to VORRd
Anton Korobeynikov7aaf94b2009-11-03 01:04:26 +000093 unsigned DestReg = MI->getOperand(0).getReg();
94
95 DEBUG({errs() << "vmov convert: "; MI->dump();});
96
Jakob Stoklund Olesenfe428082011-07-29 00:27:35 +000097 // We need to preserve imp-defs / imp-uses here. Following passes may
98 // use the register scavenger to update liveness.
99 MachineInstr *NewMI =
100 AddDefaultPred(BuildMI(MBB, *MI, MI->getDebugLoc(),
101 TII->get(ARM::VORRd), DestReg)
102 .addReg(SrcReg).addReg(SrcReg));
103 TransferImpOps(*MI, *NewMI);
Anton Korobeynikov7aaf94b2009-11-03 01:04:26 +0000104 MBB.erase(MI);
Jakob Stoklund Olesenfe428082011-07-29 00:27:35 +0000105 MI = NewMI;
Anton Korobeynikov7aaf94b2009-11-03 01:04:26 +0000106
107 DEBUG({errs() << " into: "; MI->dump();});
108
109 Modified = true;
110 ++NumVMovs;
111 } else {
Anton Korobeynikov747409a2009-11-03 18:46:11 +0000112 assert((Domain & ARMII::DomainVFP) && "Invalid domain!");
Anton Korobeynikov7aaf94b2009-11-03 01:04:26 +0000113 // Do nothing.
114 }
115 }
116
117 // Update def information.
118 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
119 const MachineOperand& MO = MI->getOperand(i);
120 if (!MO.isReg() || !MO.isDef())
121 continue;
122 unsigned MOReg = MO.getReg();
123
124 Defs[MOReg] = MI;
Jakob Stoklund Olesenfca3a252010-07-06 23:26:23 +0000125 // Catch aliases as well.
126 for (const unsigned *R = TRI->getAliasSet(MOReg); *R; ++R)
Anton Korobeynikov7aaf94b2009-11-03 01:04:26 +0000127 Defs[*R] = MI;
128 }
129 }
130
131 return Modified;
132}
133
134bool NEONMoveFixPass::runOnMachineFunction(MachineFunction &Fn) {
135 ARMFunctionInfo *AFI = Fn.getInfo<ARMFunctionInfo>();
136 const TargetMachine &TM = Fn.getTarget();
137
Evan Cheng9c207ac2010-05-17 01:11:46 +0000138 if (AFI->isThumb1OnlyFunction())
Anton Korobeynikov7aaf94b2009-11-03 01:04:26 +0000139 return false;
140
141 TRI = TM.getRegisterInfo();
Anton Korobeynikov7aaf94b2009-11-03 01:04:26 +0000142 TII = static_cast<const ARMBaseInstrInfo*>(TM.getInstrInfo());
Evan Cheng6557bce2011-02-22 19:53:14 +0000143 isA8 = TM.getSubtarget<ARMSubtarget>().isCortexA8();
Anton Korobeynikov7aaf94b2009-11-03 01:04:26 +0000144
145 bool Modified = false;
146 for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
147 ++MFI) {
148 MachineBasicBlock &MBB = *MFI;
149 Modified |= InsertMoves(MBB);
150 }
151
152 return Modified;
153}
154
155/// createNEONMoveFixPass - Returns an instance of the NEON reg-reg moves fix
156/// pass.
157FunctionPass *llvm::createNEONMoveFixPass() {
158 return new NEONMoveFixPass();
159}