aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target/AArch64/AArch64InstrInfo.cpp
diff options
context:
space:
mode:
authorStephen Hines <srhines@google.com>2014-04-23 16:57:46 -0700
committerStephen Hines <srhines@google.com>2014-04-24 15:53:16 -0700
commit36b56886974eae4f9c5ebc96befd3e7bfe5de338 (patch)
treee6cfb69fbbd937f450eeb83bfb83b9da3b01275a /lib/Target/AArch64/AArch64InstrInfo.cpp
parent69a8640022b04415ae9fac62f8ab090601d8f889 (diff)
downloadexternal_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.zip
external_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.tar.gz
external_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.tar.bz2
Update to LLVM 3.5a.
Change-Id: Ifadecab779f128e62e430c2b4f6ddd84953ed617
Diffstat (limited to 'lib/Target/AArch64/AArch64InstrInfo.cpp')
-rw-r--r--lib/Target/AArch64/AArch64InstrInfo.cpp172
1 files changed, 156 insertions, 16 deletions
diff --git a/lib/Target/AArch64/AArch64InstrInfo.cpp b/lib/Target/AArch64/AArch64InstrInfo.cpp
index 180110a..afb2034 100644
--- a/lib/Target/AArch64/AArch64InstrInfo.cpp
+++ b/lib/Target/AArch64/AArch64InstrInfo.cpp
@@ -26,7 +26,6 @@
#include "llvm/IR/Function.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/TargetRegistry.h"
-
#include <algorithm>
#define GET_INSTRINFO_CTOR_DTOR
@@ -133,8 +132,29 @@ void AArch64InstrInfo::copyPhysReg(MachineBasicBlock &MBB,
.addImm(16);
return;
}
+ } else if (AArch64::FPR8RegClass.contains(DestReg, SrcReg)) {
+ // The copy of two FPR8 registers is implemented by the copy of two FPR32
+ const TargetRegisterInfo *TRI = &getRegisterInfo();
+ unsigned Dst = TRI->getMatchingSuperReg(DestReg, AArch64::sub_8,
+ &AArch64::FPR32RegClass);
+ unsigned Src = TRI->getMatchingSuperReg(SrcReg, AArch64::sub_8,
+ &AArch64::FPR32RegClass);
+ BuildMI(MBB, I, DL, get(AArch64::FMOVss), Dst)
+ .addReg(Src);
+ return;
+ } else if (AArch64::FPR16RegClass.contains(DestReg, SrcReg)) {
+ // The copy of two FPR16 registers is implemented by the copy of two FPR32
+ const TargetRegisterInfo *TRI = &getRegisterInfo();
+ unsigned Dst = TRI->getMatchingSuperReg(DestReg, AArch64::sub_16,
+ &AArch64::FPR32RegClass);
+ unsigned Src = TRI->getMatchingSuperReg(SrcReg, AArch64::sub_16,
+ &AArch64::FPR32RegClass);
+ BuildMI(MBB, I, DL, get(AArch64::FMOVss), Dst)
+ .addReg(Src);
+ return;
} else {
- llvm_unreachable("Unknown register class in copyPhysReg");
+ CopyPhysRegTuple(MBB, I, DL, DestReg, SrcReg);
+ return;
}
// E.g. ORR xDst, xzr, xSrc, lsl #0
@@ -144,6 +164,55 @@ void AArch64InstrInfo::copyPhysReg(MachineBasicBlock &MBB,
.addImm(0);
}
+void AArch64InstrInfo::CopyPhysRegTuple(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator I,
+ DebugLoc DL, unsigned DestReg,
+ unsigned SrcReg) const {
+ unsigned SubRegs;
+ bool IsQRegs;
+ if (AArch64::DPairRegClass.contains(DestReg, SrcReg)) {
+ SubRegs = 2;
+ IsQRegs = false;
+ } else if (AArch64::DTripleRegClass.contains(DestReg, SrcReg)) {
+ SubRegs = 3;
+ IsQRegs = false;
+ } else if (AArch64::DQuadRegClass.contains(DestReg, SrcReg)) {
+ SubRegs = 4;
+ IsQRegs = false;
+ } else if (AArch64::QPairRegClass.contains(DestReg, SrcReg)) {
+ SubRegs = 2;
+ IsQRegs = true;
+ } else if (AArch64::QTripleRegClass.contains(DestReg, SrcReg)) {
+ SubRegs = 3;
+ IsQRegs = true;
+ } else if (AArch64::QQuadRegClass.contains(DestReg, SrcReg)) {
+ SubRegs = 4;
+ IsQRegs = true;
+ } else
+ llvm_unreachable("Unknown register class");
+
+ unsigned BeginIdx = IsQRegs ? AArch64::qsub_0 : AArch64::dsub_0;
+ int Spacing = 1;
+ const TargetRegisterInfo *TRI = &getRegisterInfo();
+ // Copy register tuples backward when the first Dest reg overlaps
+ // with SrcReg.
+ if (TRI->regsOverlap(SrcReg, TRI->getSubReg(DestReg, BeginIdx))) {
+ BeginIdx = BeginIdx + (SubRegs - 1);
+ Spacing = -1;
+ }
+
+ unsigned Opc = IsQRegs ? AArch64::ORRvvv_16B : AArch64::ORRvvv_8B;
+ for (unsigned i = 0; i != SubRegs; ++i) {
+ unsigned Dst = TRI->getSubReg(DestReg, BeginIdx + i * Spacing);
+ unsigned Src = TRI->getSubReg(SrcReg, BeginIdx + i * Spacing);
+ assert(Dst && Src && "Bad sub-register");
+ BuildMI(MBB, I, I->getDebugLoc(), get(Opc), Dst)
+ .addReg(Src)
+ .addReg(Src);
+ }
+ return;
+}
+
/// Does the Opcode represent a conditional branch that we can remove and re-add
/// at the end of a basic block?
static bool isCondBranch(unsigned Opc) {
@@ -418,10 +487,12 @@ AArch64InstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
default:
llvm_unreachable("Unknown size for regclass");
}
- } else {
- assert((RC->hasType(MVT::f32) || RC->hasType(MVT::f64) ||
- RC->hasType(MVT::f128))
- && "Expected integer or floating type for store");
+ } else if (AArch64::FPR8RegClass.hasSubClassEq(RC)) {
+ StoreOp = AArch64::LSFP8_STR;
+ } else if (AArch64::FPR16RegClass.hasSubClassEq(RC)) {
+ StoreOp = AArch64::LSFP16_STR;
+ } else if (RC->hasType(MVT::f32) || RC->hasType(MVT::f64) ||
+ RC->hasType(MVT::f128)) {
switch (RC->getSize()) {
case 4: StoreOp = AArch64::LSFP32_STR; break;
case 8: StoreOp = AArch64::LSFP64_STR; break;
@@ -429,6 +500,28 @@ AArch64InstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
default:
llvm_unreachable("Unknown size for regclass");
}
+ } else { // For a super register class has more than one sub registers
+ if (AArch64::DPairRegClass.hasSubClassEq(RC))
+ StoreOp = AArch64::ST1x2_8B;
+ else if (AArch64::DTripleRegClass.hasSubClassEq(RC))
+ StoreOp = AArch64::ST1x3_8B;
+ else if (AArch64::DQuadRegClass.hasSubClassEq(RC))
+ StoreOp = AArch64::ST1x4_8B;
+ else if (AArch64::QPairRegClass.hasSubClassEq(RC))
+ StoreOp = AArch64::ST1x2_16B;
+ else if (AArch64::QTripleRegClass.hasSubClassEq(RC))
+ StoreOp = AArch64::ST1x3_16B;
+ else if (AArch64::QQuadRegClass.hasSubClassEq(RC))
+ StoreOp = AArch64::ST1x4_16B;
+ else
+ llvm_unreachable("Unknown reg class");
+
+ MachineInstrBuilder NewMI = BuildMI(MBB, MBBI, DL, get(StoreOp));
+ // Vector store has different operands from other store instructions.
+ NewMI.addFrameIndex(FrameIdx)
+ .addReg(SrcReg, getKillRegState(isKill))
+ .addMemOperand(MMO);
+ return;
}
MachineInstrBuilder NewMI = BuildMI(MBB, MBBI, DL, get(StoreOp));
@@ -464,10 +557,12 @@ AArch64InstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
default:
llvm_unreachable("Unknown size for regclass");
}
- } else {
- assert((RC->hasType(MVT::f32) || RC->hasType(MVT::f64)
- || RC->hasType(MVT::f128))
- && "Expected integer or floating type for store");
+ } else if (AArch64::FPR8RegClass.hasSubClassEq(RC)) {
+ LoadOp = AArch64::LSFP8_LDR;
+ } else if (AArch64::FPR16RegClass.hasSubClassEq(RC)) {
+ LoadOp = AArch64::LSFP16_LDR;
+ } else if (RC->hasType(MVT::f32) || RC->hasType(MVT::f64) ||
+ RC->hasType(MVT::f128)) {
switch (RC->getSize()) {
case 4: LoadOp = AArch64::LSFP32_LDR; break;
case 8: LoadOp = AArch64::LSFP64_LDR; break;
@@ -475,6 +570,27 @@ AArch64InstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
default:
llvm_unreachable("Unknown size for regclass");
}
+ } else { // For a super register class has more than one sub registers
+ if (AArch64::DPairRegClass.hasSubClassEq(RC))
+ LoadOp = AArch64::LD1x2_8B;
+ else if (AArch64::DTripleRegClass.hasSubClassEq(RC))
+ LoadOp = AArch64::LD1x3_8B;
+ else if (AArch64::DQuadRegClass.hasSubClassEq(RC))
+ LoadOp = AArch64::LD1x4_8B;
+ else if (AArch64::QPairRegClass.hasSubClassEq(RC))
+ LoadOp = AArch64::LD1x2_16B;
+ else if (AArch64::QTripleRegClass.hasSubClassEq(RC))
+ LoadOp = AArch64::LD1x3_16B;
+ else if (AArch64::QQuadRegClass.hasSubClassEq(RC))
+ LoadOp = AArch64::LD1x4_16B;
+ else
+ llvm_unreachable("Unknown reg class");
+
+ MachineInstrBuilder NewMI = BuildMI(MBB, MBBI, DL, get(LoadOp), DestReg);
+ // Vector load has different operands from other load instructions.
+ NewMI.addFrameIndex(FrameIdx)
+ .addMemOperand(MMO);
+ return;
}
MachineInstrBuilder NewMI = BuildMI(MBB, MBBI, DL, get(LoadOp), DestReg);
@@ -513,7 +629,8 @@ void AArch64InstrInfo::getAddressConstraints(const MachineInstr &MI,
int &AccessScale, int &MinOffset,
int &MaxOffset) const {
switch (MI.getOpcode()) {
- default: llvm_unreachable("Unkown load/store kind");
+ default:
+ llvm_unreachable("Unknown load/store kind");
case TargetOpcode::DBG_VALUE:
AccessScale = 1;
MinOffset = INT_MIN;
@@ -572,6 +689,32 @@ void AArch64InstrInfo::getAddressConstraints(const MachineInstr &MI,
MinOffset = -0x40 * AccessScale;
MaxOffset = 0x3f * AccessScale;
return;
+ case AArch64::LD1x2_8B: case AArch64::ST1x2_8B:
+ AccessScale = 16;
+ MinOffset = 0;
+ MaxOffset = 0xfff * AccessScale;
+ return;
+ case AArch64::LD1x3_8B: case AArch64::ST1x3_8B:
+ AccessScale = 24;
+ MinOffset = 0;
+ MaxOffset = 0xfff * AccessScale;
+ return;
+ case AArch64::LD1x4_8B: case AArch64::ST1x4_8B:
+ case AArch64::LD1x2_16B: case AArch64::ST1x2_16B:
+ AccessScale = 32;
+ MinOffset = 0;
+ MaxOffset = 0xfff * AccessScale;
+ return;
+ case AArch64::LD1x3_16B: case AArch64::ST1x3_16B:
+ AccessScale = 48;
+ MinOffset = 0;
+ MaxOffset = 0xfff * AccessScale;
+ return;
+ case AArch64::LD1x4_16B: case AArch64::ST1x4_16B:
+ AccessScale = 64;
+ MinOffset = 0;
+ MaxOffset = 0xfff * AccessScale;
+ return;
}
}
@@ -587,18 +730,15 @@ unsigned AArch64InstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
if (MI.getOpcode() == AArch64::INLINEASM)
return getInlineAsmLength(MI.getOperand(0).getSymbolName(), MAI);
- if (MI.isLabel())
- return 0;
-
switch (MI.getOpcode()) {
case TargetOpcode::BUNDLE:
return getInstBundleLength(MI);
case TargetOpcode::IMPLICIT_DEF:
case TargetOpcode::KILL:
- case TargetOpcode::PROLOG_LABEL:
+ case TargetOpcode::CFI_INSTRUCTION:
case TargetOpcode::EH_LABEL:
+ case TargetOpcode::GC_LABEL:
case TargetOpcode::DBG_VALUE:
- return 0;
case AArch64::TLSDESCCALL:
return 0;
default: