1 //===-- NEONMoveFix.cpp - Convert vfp reg-reg moves into neon ---*- C++ -*-===//
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 #define DEBUG_TYPE "neon-mov-fix"
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"
22 STATISTIC(NumVMovs, "Number of reg-reg moves converted");
25 struct NEONMoveFixPass : public MachineFunctionPass {
27 NEONMoveFixPass() : MachineFunctionPass(ID) {}
29 virtual bool runOnMachineFunction(MachineFunction &Fn);
31 virtual const char *getPassName() const {
32 return "NEON reg-reg move conversion";
36 const TargetRegisterInfo *TRI;
37 const ARMBaseInstrInfo *TII;
40 typedef DenseMap<unsigned, const MachineInstr*> RegMap;
42 bool InsertMoves(MachineBasicBlock &MBB);
44 void TransferImpOps(MachineInstr &Old, MachineInstr &New);
46 char NEONMoveFixPass::ID = 0;
49 static bool inNEONDomain(unsigned Domain, bool isA8) {
50 return (Domain & ARMII::DomainNEON) ||
51 (isA8 && (Domain & ARMII::DomainNEONA8));
54 /// Transfer implicit kill and def operands from Old to New.
55 void 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())
64 bool NEONMoveFixPass::InsertMoves(MachineBasicBlock &MBB) {
66 bool Modified = false;
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) {
72 NextMII = llvm::next(MII);
73 MachineInstr *MI = &*MII;
75 if (MI->getOpcode() == ARM::VMOVD &&
76 !TII->isPredicated(MI)) {
77 unsigned SrcReg = MI->getOperand(1).getReg();
78 // If we do not find an instruction defining the reg, this means the
79 // 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;
91 if (inNEONDomain(Domain, isA8)) {
92 // Convert VMOVD to VORRd
93 unsigned DestReg = MI->getOperand(0).getReg();
95 DEBUG({errs() << "vmov convert: "; MI->dump();});
97 // We need to preserve imp-defs / imp-uses here. Following passes may
98 // use the register scavenger to update liveness.
100 AddDefaultPred(BuildMI(MBB, *MI, MI->getDebugLoc(),
101 TII->get(ARM::VORRd), DestReg)
102 .addReg(SrcReg).addReg(SrcReg));
103 TransferImpOps(*MI, *NewMI);
107 DEBUG({errs() << " into: "; MI->dump();});
112 assert((Domain & ARMII::DomainVFP) && "Invalid domain!");
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())
122 unsigned MOReg = MO.getReg();
125 // Catch aliases as well.
126 for (const unsigned *R = TRI->getAliasSet(MOReg); *R; ++R)
134 bool NEONMoveFixPass::runOnMachineFunction(MachineFunction &Fn) {
135 ARMFunctionInfo *AFI = Fn.getInfo<ARMFunctionInfo>();
136 const TargetMachine &TM = Fn.getTarget();
138 if (AFI->isThumb1OnlyFunction())
141 TRI = TM.getRegisterInfo();
142 TII = static_cast<const ARMBaseInstrInfo*>(TM.getInstrInfo());
143 isA8 = TM.getSubtarget<ARMSubtarget>().isCortexA8();
145 bool Modified = false;
146 for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
148 MachineBasicBlock &MBB = *MFI;
149 Modified |= InsertMoves(MBB);
155 /// createNEONMoveFixPass - Returns an instance of the NEON reg-reg moves fix
157 FunctionPass *llvm::createNEONMoveFixPass() {
158 return new NEONMoveFixPass();