mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-14 00:32:55 +00:00
Use NEON reg-reg moves, where profitable. This reduces "domain-cross" stalls, when we used to mix vfp and neon code (the former were used for reg-reg moves)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@85764 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
f57b1baa44
commit
f95215f551
@ -125,12 +125,16 @@ def ARMInstrInfo : InstrInfo {
|
||||
"SizeFlag",
|
||||
"IndexModeBits",
|
||||
"Form",
|
||||
"isUnaryDataProc"];
|
||||
"isUnaryDataProc",
|
||||
"canXformTo16Bit",
|
||||
"Dom"];
|
||||
let TSFlagsShifts = [0,
|
||||
4,
|
||||
7,
|
||||
9,
|
||||
15];
|
||||
15,
|
||||
16,
|
||||
17];
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -16,15 +16,18 @@
|
||||
#include "ARMAddressingModes.h"
|
||||
#include "ARMGenInstrInfo.inc"
|
||||
#include "ARMMachineFunctionInfo.h"
|
||||
#include "ARMRegisterInfo.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/CodeGen/LiveVariables.h"
|
||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/MachineJumpTableInfo.h"
|
||||
#include "llvm/CodeGen/MachineMemOperand.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/CodeGen/PseudoSourceValue.h"
|
||||
#include "llvm/MC/MCAsmInfo.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
using namespace llvm;
|
||||
|
||||
@ -32,8 +35,9 @@ static cl::opt<bool>
|
||||
EnableARM3Addr("enable-arm-3-addr-conv", cl::Hidden,
|
||||
cl::desc("Enable ARM 2-addr to 3-addr conv"));
|
||||
|
||||
ARMBaseInstrInfo::ARMBaseInstrInfo()
|
||||
: TargetInstrInfoImpl(ARMInsts, array_lengthof(ARMInsts)) {
|
||||
ARMBaseInstrInfo::ARMBaseInstrInfo(const ARMSubtarget& STI)
|
||||
: TargetInstrInfoImpl(ARMInsts, array_lengthof(ARMInsts)),
|
||||
Subtarget(STI) {
|
||||
}
|
||||
|
||||
MachineInstr *
|
||||
@ -504,7 +508,7 @@ ARMBaseInstrInfo::isMoveInstr(const MachineInstr &MI,
|
||||
case ARM::FCPYS:
|
||||
case ARM::FCPYD:
|
||||
case ARM::VMOVD:
|
||||
case ARM::VMOVQ: {
|
||||
case ARM::VMOVQ: {
|
||||
SrcReg = MI.getOperand(1).getReg();
|
||||
DstReg = MI.getOperand(0).getReg();
|
||||
return true;
|
||||
@ -647,11 +651,45 @@ ARMBaseInstrInfo::copyRegToReg(MachineBasicBlock &MBB,
|
||||
} else if (DestRC == ARM::SPRRegisterClass) {
|
||||
AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::FCPYS), DestReg)
|
||||
.addReg(SrcReg));
|
||||
} else if ((DestRC == ARM::DPRRegisterClass) ||
|
||||
(DestRC == ARM::DPR_VFP2RegisterClass) ||
|
||||
(DestRC == ARM::DPR_8RegisterClass)) {
|
||||
AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::FCPYD), DestReg)
|
||||
.addReg(SrcReg));
|
||||
} else if (DestRC == ARM::DPR_VFP2RegisterClass ||
|
||||
DestRC == ARM::DPR_8RegisterClass ||
|
||||
SrcRC == ARM::DPR_VFP2RegisterClass ||
|
||||
SrcRC == ARM::DPR_8RegisterClass) {
|
||||
// Always use neon reg-reg move if source or dest is NEON-only regclass.
|
||||
BuildMI(MBB, I, DL, get(ARM::VMOVD), DestReg).addReg(SrcReg);
|
||||
} else if (DestRC == ARM::DPRRegisterClass) {
|
||||
const ARMBaseRegisterInfo* TRI = &getRegisterInfo();
|
||||
|
||||
// Find the Machine Instruction which defines SrcReg.
|
||||
MachineBasicBlock::iterator J = (I == MBB.begin() ? I : prior(I));
|
||||
while (J != MBB.begin()) {
|
||||
if (J->modifiesRegister(SrcReg, TRI))
|
||||
break;
|
||||
--J;
|
||||
}
|
||||
|
||||
unsigned Domain;
|
||||
if (J->modifiesRegister(SrcReg, TRI)) {
|
||||
Domain = J->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;
|
||||
} else {
|
||||
// We reached the beginning of the BB and found no instruction defining
|
||||
// the reg. This means that register should be live-in for this BB.
|
||||
// It's always to better to use NEON reg-reg moves.
|
||||
Domain = ARMII::DomainNEON;
|
||||
}
|
||||
|
||||
if ((Domain & ARMII::DomainNEON) && getSubtarget().hasNEON()) {
|
||||
BuildMI(MBB, I, DL, get(ARM::VMOVQ), DestReg).addReg(SrcReg);
|
||||
} else {
|
||||
assert((Domain & ARMII::DomainVFP ||
|
||||
!getSubtarget().hasNEON()) && "Invalid domain!");
|
||||
AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::FCPYD), DestReg)
|
||||
.addReg(SrcReg));
|
||||
}
|
||||
} else if (DestRC == ARM::QPRRegisterClass ||
|
||||
DestRC == ARM::QPR_VFP2RegisterClass) {
|
||||
BuildMI(MBB, I, DL, get(ARM::VMOVQ), DestReg).addReg(SrcReg);
|
||||
|
@ -130,6 +130,14 @@ namespace ARMII {
|
||||
// a 16-bit Thumb instruction if certain conditions are met.
|
||||
Xform16Bit = 1 << 16,
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// Code domain.
|
||||
DomainShift = 17,
|
||||
DomainMask = 3 << DomainShift,
|
||||
DomainGeneral = 0 << DomainShift,
|
||||
DomainVFP = 1 << DomainShift,
|
||||
DomainNEON = 2 << DomainShift,
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// Field shifts - such shifts are used to set field while generating
|
||||
// machine instructions.
|
||||
@ -157,9 +165,10 @@ namespace ARMII {
|
||||
}
|
||||
|
||||
class ARMBaseInstrInfo : public TargetInstrInfoImpl {
|
||||
const ARMSubtarget& Subtarget;
|
||||
protected:
|
||||
// Can be only subclassed.
|
||||
explicit ARMBaseInstrInfo();
|
||||
explicit ARMBaseInstrInfo(const ARMSubtarget &STI);
|
||||
public:
|
||||
// Return the non-pre/post incrementing version of 'Opc'. Return 0
|
||||
// if there is not such an opcode.
|
||||
@ -173,6 +182,7 @@ public:
|
||||
LiveVariables *LV) const;
|
||||
|
||||
virtual const ARMBaseRegisterInfo &getRegisterInfo() const =0;
|
||||
const ARMSubtarget &getSubtarget() const { return Subtarget; }
|
||||
|
||||
// Branch analysis.
|
||||
virtual bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
|
||||
|
@ -108,6 +108,15 @@ def IndexModeNone : IndexMode<0>;
|
||||
def IndexModePre : IndexMode<1>;
|
||||
def IndexModePost : IndexMode<2>;
|
||||
|
||||
// Instruction execution domain.
|
||||
class Domain<bits<2> val> {
|
||||
bits<2> Value = val;
|
||||
}
|
||||
def GenericDomain : Domain<0>;
|
||||
def VFPDomain : Domain<1>; // Instructions in VFP domain only
|
||||
def NeonDomain : Domain<2>; // Instructions in Neon domain only
|
||||
def VFPNeonDomain : Domain<3>; // Instructions in both VFP & Neon domains
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// ARM special operands.
|
||||
@ -136,7 +145,7 @@ def s_cc_out : OptionalDefOperand<OtherVT, (ops CCR), (ops (i32 CPSR))> {
|
||||
//
|
||||
|
||||
class InstARM<AddrMode am, SizeFlagVal sz, IndexMode im,
|
||||
Format f, string cstr, InstrItinClass itin>
|
||||
Format f, Domain d, string cstr, InstrItinClass itin>
|
||||
: Instruction {
|
||||
field bits<32> Inst;
|
||||
|
||||
@ -155,6 +164,9 @@ class InstARM<AddrMode am, SizeFlagVal sz, IndexMode im,
|
||||
Format F = f;
|
||||
bits<5> Form = F.Value;
|
||||
|
||||
Domain D = d;
|
||||
bits<2> Dom = D.Value;
|
||||
|
||||
//
|
||||
// Attributes specific to ARM instructions...
|
||||
//
|
||||
@ -167,7 +179,8 @@ class InstARM<AddrMode am, SizeFlagVal sz, IndexMode im,
|
||||
|
||||
class PseudoInst<dag oops, dag iops, InstrItinClass itin,
|
||||
string asm, list<dag> pattern>
|
||||
: InstARM<AddrModeNone, SizeSpecial, IndexModeNone, Pseudo, "", itin> {
|
||||
: InstARM<AddrModeNone, SizeSpecial, IndexModeNone, Pseudo, GenericDomain,
|
||||
"", itin> {
|
||||
let OutOperandList = oops;
|
||||
let InOperandList = iops;
|
||||
let AsmString = asm;
|
||||
@ -179,7 +192,7 @@ class I<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
|
||||
IndexMode im, Format f, InstrItinClass itin,
|
||||
string opc, string asm, string cstr,
|
||||
list<dag> pattern>
|
||||
: InstARM<am, sz, im, f, cstr, itin> {
|
||||
: InstARM<am, sz, im, f, GenericDomain, cstr, itin> {
|
||||
let OutOperandList = oops;
|
||||
let InOperandList = !con(iops, (ops pred:$p));
|
||||
let AsmString = !strconcat(opc, !strconcat("${p}", asm));
|
||||
@ -194,7 +207,7 @@ class sI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
|
||||
IndexMode im, Format f, InstrItinClass itin,
|
||||
string opc, string asm, string cstr,
|
||||
list<dag> pattern>
|
||||
: InstARM<am, sz, im, f, cstr, itin> {
|
||||
: InstARM<am, sz, im, f, GenericDomain, cstr, itin> {
|
||||
let OutOperandList = oops;
|
||||
let InOperandList = !con(iops, (ops pred:$p, cc_out:$s));
|
||||
let AsmString = !strconcat(opc, !strconcat("${p}${s}", asm));
|
||||
@ -206,7 +219,7 @@ class sI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
|
||||
class XI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
|
||||
IndexMode im, Format f, InstrItinClass itin,
|
||||
string asm, string cstr, list<dag> pattern>
|
||||
: InstARM<am, sz, im, f, cstr, itin> {
|
||||
: InstARM<am, sz, im, f, GenericDomain, cstr, itin> {
|
||||
let OutOperandList = oops;
|
||||
let InOperandList = iops;
|
||||
let AsmString = asm;
|
||||
@ -807,7 +820,7 @@ class ARMV6Pat<dag pattern, dag result> : Pat<pattern, result> {
|
||||
|
||||
class ThumbI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
|
||||
InstrItinClass itin, string asm, string cstr, list<dag> pattern>
|
||||
: InstARM<am, sz, IndexModeNone, ThumbFrm, cstr, itin> {
|
||||
: InstARM<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> {
|
||||
let OutOperandList = oops;
|
||||
let InOperandList = iops;
|
||||
let AsmString = asm;
|
||||
@ -833,7 +846,7 @@ class TJTI<dag oops, dag iops, InstrItinClass itin, string asm, list<dag> patter
|
||||
// Thumb1 only
|
||||
class Thumb1I<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
|
||||
InstrItinClass itin, string asm, string cstr, list<dag> pattern>
|
||||
: InstARM<am, sz, IndexModeNone, ThumbFrm, cstr, itin> {
|
||||
: InstARM<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> {
|
||||
let OutOperandList = oops;
|
||||
let InOperandList = iops;
|
||||
let AsmString = asm;
|
||||
@ -861,7 +874,7 @@ class T1It<dag oops, dag iops, InstrItinClass itin,
|
||||
class Thumb1sI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
|
||||
InstrItinClass itin,
|
||||
string opc, string asm, string cstr, list<dag> pattern>
|
||||
: InstARM<am, sz, IndexModeNone, ThumbFrm, cstr, itin> {
|
||||
: InstARM<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> {
|
||||
let OutOperandList = !con(oops, (ops s_cc_out:$s));
|
||||
let InOperandList = !con(iops, (ops pred:$p));
|
||||
let AsmString = !strconcat(opc, !strconcat("${s}${p}", asm));
|
||||
@ -883,7 +896,7 @@ class T1sIt<dag oops, dag iops, InstrItinClass itin,
|
||||
class Thumb1pI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
|
||||
InstrItinClass itin,
|
||||
string opc, string asm, string cstr, list<dag> pattern>
|
||||
: InstARM<am, sz, IndexModeNone, ThumbFrm, cstr, itin> {
|
||||
: InstARM<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> {
|
||||
let OutOperandList = oops;
|
||||
let InOperandList = !con(iops, (ops pred:$p));
|
||||
let AsmString = !strconcat(opc, !strconcat("${p}", asm));
|
||||
@ -918,7 +931,7 @@ class T1pIs<dag oops, dag iops,
|
||||
class Thumb2I<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
|
||||
InstrItinClass itin,
|
||||
string opc, string asm, string cstr, list<dag> pattern>
|
||||
: InstARM<am, sz, IndexModeNone, ThumbFrm, cstr, itin> {
|
||||
: InstARM<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> {
|
||||
let OutOperandList = oops;
|
||||
let InOperandList = !con(iops, (ops pred:$p));
|
||||
let AsmString = !strconcat(opc, !strconcat("${p}", asm));
|
||||
@ -934,7 +947,7 @@ class Thumb2I<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
|
||||
class Thumb2sI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
|
||||
InstrItinClass itin,
|
||||
string opc, string asm, string cstr, list<dag> pattern>
|
||||
: InstARM<am, sz, IndexModeNone, ThumbFrm, cstr, itin> {
|
||||
: InstARM<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> {
|
||||
let OutOperandList = oops;
|
||||
let InOperandList = !con(iops, (ops pred:$p, cc_out:$s));
|
||||
let AsmString = !strconcat(opc, !strconcat("${s}${p}", asm));
|
||||
@ -946,7 +959,7 @@ class Thumb2sI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
|
||||
class Thumb2XI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
|
||||
InstrItinClass itin,
|
||||
string asm, string cstr, list<dag> pattern>
|
||||
: InstARM<am, sz, IndexModeNone, ThumbFrm, cstr, itin> {
|
||||
: InstARM<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> {
|
||||
let OutOperandList = oops;
|
||||
let InOperandList = iops;
|
||||
let AsmString = asm;
|
||||
@ -993,7 +1006,7 @@ class T2Ix2<dag oops, dag iops, InstrItinClass itin,
|
||||
class T2Iidxldst<dag oops, dag iops, AddrMode am, IndexMode im,
|
||||
InstrItinClass itin,
|
||||
string opc, string asm, string cstr, list<dag> pattern>
|
||||
: InstARM<am, Size4Bytes, im, ThumbFrm, cstr, itin> {
|
||||
: InstARM<am, Size4Bytes, im, ThumbFrm, GenericDomain, cstr, itin> {
|
||||
let OutOperandList = oops;
|
||||
let InOperandList = !con(iops, (ops pred:$p));
|
||||
let AsmString = !strconcat(opc, !strconcat("${p}", asm));
|
||||
@ -1026,7 +1039,7 @@ class T2Pat<dag pattern, dag result> : Pat<pattern, result> {
|
||||
class VFPI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
|
||||
IndexMode im, Format f, InstrItinClass itin,
|
||||
string opc, string asm, string cstr, list<dag> pattern>
|
||||
: InstARM<am, sz, im, f, cstr, itin> {
|
||||
: InstARM<am, sz, im, f, VFPDomain, cstr, itin> {
|
||||
let OutOperandList = oops;
|
||||
let InOperandList = !con(iops, (ops pred:$p));
|
||||
let AsmString = !strconcat(opc, !strconcat("${p}", asm));
|
||||
@ -1038,7 +1051,7 @@ class VFPI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
|
||||
class VFPXI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
|
||||
IndexMode im, Format f, InstrItinClass itin,
|
||||
string asm, string cstr, list<dag> pattern>
|
||||
: InstARM<am, sz, im, f, cstr, itin> {
|
||||
: InstARM<am, sz, im, f, VFPDomain, cstr, itin> {
|
||||
let OutOperandList = oops;
|
||||
let InOperandList = iops;
|
||||
let AsmString = asm;
|
||||
@ -1199,7 +1212,7 @@ class AVConv5I<bits<8> opcod1, bits<4> opcod2, dag oops, dag iops,
|
||||
|
||||
class NeonI<dag oops, dag iops, AddrMode am, IndexMode im, InstrItinClass itin,
|
||||
string asm, string cstr, list<dag> pattern>
|
||||
: InstARM<am, Size4Bytes, im, NEONFrm, cstr, itin> {
|
||||
: InstARM<am, Size4Bytes, im, NEONFrm, NeonDomain, cstr, itin> {
|
||||
let OutOperandList = oops;
|
||||
let InOperandList = iops;
|
||||
let AsmString = asm;
|
||||
|
@ -25,7 +25,7 @@
|
||||
using namespace llvm;
|
||||
|
||||
ARMInstrInfo::ARMInstrInfo(const ARMSubtarget &STI)
|
||||
: RI(*this, STI), Subtarget(STI) {
|
||||
: ARMBaseInstrInfo(STI), RI(*this, STI) {
|
||||
}
|
||||
|
||||
unsigned ARMInstrInfo::getUnindexedOpcode(unsigned Opc) const {
|
||||
|
@ -25,7 +25,6 @@ namespace llvm {
|
||||
|
||||
class ARMInstrInfo : public ARMBaseInstrInfo {
|
||||
ARMRegisterInfo RI;
|
||||
const ARMSubtarget &Subtarget;
|
||||
public:
|
||||
explicit ARMInstrInfo(const ARMSubtarget &STI);
|
||||
|
||||
|
@ -24,7 +24,8 @@
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
Thumb1InstrInfo::Thumb1InstrInfo(const ARMSubtarget &STI) : RI(*this, STI) {
|
||||
Thumb1InstrInfo::Thumb1InstrInfo(const ARMSubtarget &STI)
|
||||
: ARMBaseInstrInfo(STI), RI(*this, STI) {
|
||||
}
|
||||
|
||||
unsigned Thumb1InstrInfo::getUnindexedOpcode(unsigned Opc) const {
|
||||
|
@ -25,7 +25,8 @@
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
Thumb2InstrInfo::Thumb2InstrInfo(const ARMSubtarget &STI) : RI(*this, STI) {
|
||||
Thumb2InstrInfo::Thumb2InstrInfo(const ARMSubtarget &STI)
|
||||
: ARMBaseInstrInfo(STI), RI(*this, STI) {
|
||||
}
|
||||
|
||||
unsigned Thumb2InstrInfo::getUnindexedOpcode(unsigned Opc) const {
|
||||
|
Loading…
x
Reference in New Issue
Block a user