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