mirror of
https://github.com/opnsense/src.git
synced 2026-02-13 07:44:48 -05:00
There are several bugfixes in this update, but the most important one is to ensure __start_ and __stop_ symbols for linker sets and kernel module metadata are always emitted in object files: http://llvm.org/bugs/show_bug.cgi?id=9292 Before this fix, if you compiled kernel modules with clang, they would not be properly processed by kldxref, and if they had any dependencies, the kernel would fail to load those. Another problem occurred when attempting to mount a tmpfs filesystem, which would result in 'operation not supported by device'.
148 lines
4.5 KiB
C++
148 lines
4.5 KiB
C++
//===-- 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();
|
|
}
|